При динамическом добавлении элемента состояние остается со значением по умолчанию внутри этого элемента

#reactjs

#reactjs

Вопрос:

Я пытаюсь динамически добавлять button к своему компоненту при выборе значения в select . Добавление кнопки на мою страницу работает нормально, но состояние компонента внутри функции обратного вызова кнопки остается со значением по умолчанию.

У меня есть следующая реализация:

 const Component = () => {
  const [value, setValue] = useState('');
  const [buttons, setButtons] = useState([]);
  
  const onChangeValue = (e) => {
    setValue(e.target.value);
    setButtons([...buttons,
      <button
        onClick={() => console.log(value)} // displays '' which is the default state
      >
        Try me
      </button>
    ]);
  }

  return (
    <div>
      <select onChange={onChangeValue}>
        <option value={1}>Option #1</option>
        <option value={2}>Option #2</option>
        <option value={3}>Option #3</option>
      </select>
      {buttons}
    </div>
  );
}
  

Я бы предположил, что состояние моего компонента не «подключено» к кнопкам, но я не уверен, как я могу это сделать.

Ответ №1:

Я думаю, что событие onClick пытается записать в консоль неправильную переменную. Вы должны поместить event.target.value вместо просто значения.

Ответ №2:

Вы можете создавать пользовательские компоненты и передавать динамическое значение из useState в качестве реквизита:

 const Component = () => {
  const [value, setValue] = useState('');
  const [buttons, setButtons] = useState([]);
  
  const onChangeValue = (e) => {
    setValue(e.target.value);
    setButtons([...buttons,
      (props) => <button
        onClick={() => console.log(props.value)} 
      >
        Try me
      </button>
    ]);
  }

  return (
    <div>
      <select onChange={onChangeValue}>
        <option value={1}>Option #1</option>
        <option value={2}>Option #2</option>
        <option value={3}>Option #3</option>
      </select>
      {buttons.map((B, i) => <B key={i} value={value}/>)}
    </div>
  );
}
  

Ответ №3:

Проблема в вашем коде из-за того, что useState поскольку useState он асинхронный. Итак, во время создания компонента значение «пустое», поскольку оно не обновляется из-за асинхронности. Лучший способ — это вид закрытия, который запоминает его состояние. Вы можете просто сделать это, сохранив переменное состояние:

Вот код:

 const Component = () => {
  const [value, setValue] = useState("");
  const [buttons, setButtons] = useState([]);

  const handleClick = (val) => console.log(val);

  const onChangeValue = (e) => {
    e.persist();
    const val = e.target.value;
    setValue(e.target.value);
    if (buttons.length < 3) {
      //avoid unnecessary addition
      setButtons([
        ...buttons,
        <button
          key={value}
          onClick={() => handleClick(val)} // displays '' which is the default state
        >
          Try me
        </button>
      ]);
    }
  }
  

Вот демонстрация:https://codesandbox.io/s/sharp-oskar-qnm51?file=/src/App.js:65-633