简体   繁体   中英

Input field loses focus after typing one character in react app

In my case I have a dropdown and based on the number selected with the dropdown some input fields appear. When I type into the input field the focus on that input field is lost after typing one character. Setting a unique key for each field is not solving my problem.

Link to the project: https://codesandbox.io/s/stoic-brahmagupta-m5014


const ItemPrice = () => {
  const data = itemData.doReservation.eventPackage.item;

  let emptyCat = {};
  let emptyQnt = {};
  let promoNum = {};
  let emptyPromotion = {};

  const [promoNumber, setPromoNumber] = useState(promoNum);

  for (let it in data) {
    let cat = {};
    let promo = {};

    for (let bt in data[it].buyertypes) {
      cat[data[it].buyertypes[bt].id] = "";
      emptyQnt[data[it].buyertypes[bt].id] = 0;
      promo[data[it].buyertypes[bt].id] = "";
      promoNum[data[it].buyertypes[bt].id] = [];
      emptyPromotion[data[it].buyertypes[bt].id] = {};
    }
    emptyCat[data[it].id] = cat;
    cat = {};
  }

  const [quantity, setQuantity] = useState(emptyQnt);
  const [code, setCode] = useState(emptyPromotion);

  const handleQuantity = (e) => {
    const name = e.target.name;
    const value = e.target.value;
    setQuantity({
      ...quantity,
      [name]: value
    });
    let num = [];
    for (let i = 1; i <= value; i++) {
      num.push(i);
    }
    setPromoNumber({ ...promoNumber, [name]: num });
    let num2 = {};
    for (let pn = 1; pn <= value; pn++) {
      if (code[name]["code" + name + pn] === undefined) {
        num2["code" + name + pn] = "";
      } else {
        num2["code" + name + pn] = code[name]["code" + name + pn];
      }
    }
    setCode({ ...code, [name]: num2 });
  };

  const handleCode = (e) => {
    e.preventDefault();
    const sp = e.target.name.split(",");
    const id1 = sp[0];
    const id2 = sp[1];
    const value = e.target.value;
    setCode({
      ...code,
      [id1]: {
        ...code[id1],
        [id2]: value
      }
    });
  };

  const ShowData = () => {
    let buyerTypes = [];
    let items = [];
    if (data) {
      for (let it in data) {
        items.push(
          <div className="selectionHeader">
            <div className="selHeadType">type</div>
            <div className="selHeadQnt">Quantity</div>
            <div className="selHeadCat">Price category</div>
          </div>
        );
        for (let bt in data[it].buyertypes) {
          buyerTypes.push({
            dsc: data[it].buyertypes[bt].description,
            qntId: data[it].buyertypes[bt].id
          });
        }
        items.push(
          <div>
            {buyerTypes.map((i, index) => (
              <div key={`a${index}`} className="selectionRowComp">
                <div key={`c${index}`} className="selectionRow">
                  <h4 className="btDescription">{i.dsc}</h4>
                  <div className="NumberDropDown">
                    <select
                      value={quantity[i.qntId]}
                      onChange={handleQuantity}
                      name={i.qntId}
                    >
                      {[0, 1, 2, 3, 4, 5, 6].map((l) => {
                        return (
                          <option value={l} key={l}>
                            {l}
                          </option>
                        );
                      })}
                    </select>
                  </div>
                </div>
                <div>
                  {promoNumber[i.qntId].map((p, index) => (
                    <div key={`s${index}`}>
                      <label className="codeLabel">code {p}: </label>
                      <input
                        className="codeInput"
                        type="text"
                        value={code[i.qntId]["code" + i.qntId + (index + 1)]}
                        onChange={handleCode}
                        name={[i.qntId, "code" + i.qntId + (index + 1)]}
                        // required={hasPromotion[i.qntId]}
                      />
                    </div>
                  ))}
                </div>
              </div>
            ))}
          </div>
        );
        buyerTypes = [];
      }
    }
    return (
      <div className="selectionItem">
        {items.map((it, index) => {
          return <div key={`w${index}`}> {it}</div>;
        })}
      </div>
    );
  };

  const handleSubmit = (e) => {
    e.preventDefault();
  };

  return (
    <div>
      <div>
        <div>
          <form onSubmit={handleSubmit}>
            <ShowData />
          </form>
        </div>
      </div>
    </div>
  );
};

You have to decouple Parent ( ItemPrice ) and Child ( ShowData ) components respectively.

A through re-factor of your code is needed. Because dependencies like const data is defined in ItemPrise and used in child component ShowData , rather it should be sent down as Props to ShowData component.

ShowData component should not be directly dependent on any variable/const defined in ItemPrise component. All such dependencies should be passed using any of the following basis your use-case and application requirements:

  1. Props
  2. Context
  3. Global state management such as Redux
  4. Custom Hook

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM