Реагировать на хуки - нельзя ввести в поле ввода [НЕ дублировать] - PullRequest
0 голосов
/ 07 мая 2020

Вы можете проверить полный код здесь: CODESANDBOX LINK

Это действительно странно. У меня есть список полей ввода, которые отображаются динамически в зависимости от нажатия кнопки

const newFields = (index) =>
<div>
    <input value={inputs[index].name}  onChange={e => handleNameInput(e,index)} />
    <input value={inputs[index].age} type="number" onChange={e => handleAgeInput(e,index)} />
    <Button onClick={() => setInputArray(inputArray => [...inputArray, newFields(++index)])}>Add</Button>
</div>

Я пытаюсь сохранить значения входов и обновить их onChange. Но, как указано в заголовке, я не могу вводить текст в поле ввода, и как только я щелкаю символ, ввод теряет фокус. Я не знаю, почему это происходит.

Вот состояния и функция handleInput:

  let [inputs, setInputs] = useState(Array.apply(null, Array(100)).map(function () { return {
    name: '',
    age: ''
  } }));

const handleNameInput = (e, i) =>{
  let tempArr = new Array();
  tempArr = [...inputs];
  tempArr[i].name = e.target.value;
  setInputs([...tempArr]);
}

//handleAgeInput is exactly the same

1 Ответ

0 голосов
/ 07 мая 2020

Думаю, ваша главная проблема - это дублирование использования массивов. Дело в том, что вам нужен только один массив данных. Итак, вам нужно построить вокруг него свой компонент. Если вы создаете еще один массив в состоянии, вы увеличиваете сложность, и это приводит к вашей текущей проблеме.

Поймите, почему нет обновлений

Вы onChange обновление вызова функции состояние массива inputs. НО, вы визуализируете inputArray, где для него ничего не меняется. Нет setInputArray звоните так, без повторного рендеринга.

Предложение

Есть предложение по реализации того, что, как я понимаю, вам необходимо:

function App() {
  let [inputArray, setInputArray] = useState([{
    name: "",
    age: ""
  }]);

  const handleNameInput = useCallback(
    (e, i) => {
      inputArray[i].name = e.target.value;
      setInputArray([...inputArray]);
    },
    [inputArray]
  );

  const handleAgeInput = useCallback(
    (e, i) => {
      inputArray[i].age = e.target.value;
      setInputArray([...inputArray]);
    },
    [inputArray]
  );

  const handleNewField = useCallback(() =>
    setInputArray(inputArray => [...inputArray, {
      name: "",
      age: ""
    }]),
    []
  );

  return (
    <div className="App">
      {inputArray.map((element, i) => (
        <div>
          <input
            value={element.name}
            onChange={e => handleNameInput(e, i)}
          />
          <input
            value={element.age}
            type="number"
            onChange={e => handleAgeInput(e, i)}
          />
          <button
            onClick={handleNewField}>
            Add
          </button>
        </div>
      ))}
    </div>
  );
}

В зависимости от ваших потребностей может тебе стоит его адаптировать. Есть несколько способов избежать повторной визуализации всего списка. Но таким образом вы можете редактировать все поля.

Еще один правильный способ сделать это - сделать каждую группу полей как другой компонент. С независимыми состояниями.

Если вы хотите, чтобы кнопка была нажата один раз, переместите его из l oop.

Если вы хотите отображать только последние установленные поля, возьмите inputArrays[inputArray.length] вместо l oop для всех.

Пояснение:

Вы визуализируете массив компонентов { inputArray.map((e, i) => { return <div key={i}> {e} </div>; })}, где e должен быть компонентом.

С другой стороны, вы поддерживаете массив данных, который «затеняет» первый массив.

Основная концепция вашего варианта использования, насколько я понимаю, должна заключаться в визуализации ваших компонентов непосредственно из ваших данных - вашего массива данных. Таким образом, у вас будет только один источник истины.

...