Переключатель onChange в вызывает нежелательное изменение значений в состоянии

#javascript #reactjs #accordion #reactstrap

Вопрос:

 const [toggleValue, setToggleValue] = useState();
..
..
    {Items.map((item) => (
      <Card onClick={() => setToggleValue(item.id)} key={item.id}>
        <CardHeader text={item.text} />
        <Collapse isOpen={toggleValue=== item.id}>
          <CardBody>
               <FormGroup>
                  <CustomInput value="1" type="radio" id="yes" onChange={handleOptionChange(item.id, '1')} />
                  <CustomInput value="2" type="radio" id="yes" onChange={handleOptionChange(item.id, '2')} />
               </FormGroup>
          </CardBody>
        </Collapse>
     </Card>
 

Он работает по назначению, но когда я использую переключатель для выбора опции на любой из этих карт, он автоматически сворачивает текущую карту и разворачивает первую карту. Функция handleOptionChange, которая запускается при выборе переключателя, также изменяет другое значение в состоянии с помощью useState:

 const handleOptionChange = (name, value) => () => {
   const Item = name;
   const numericValue = Number(value);
   setFormData({
      ...data,
      id: Item,
      vote: numericValue,
   });
};
 

Ответ №1:

handleOptionChange(item.id, ‘1’) не следует напрямую вызывать onChange

 const [toggleValue, setToggleValue] = useState();
..
..
    {Items.map((item) => (
      <Card onClick={() => setToggleValue(item.id)} key={item.id}>
        <CardHeader text={item.text} />
        <Collapse isOpen={toggleValue=== item.id}>
          <CardBody>
               <FormGroup>
                  <CustomInput value="1" type="radio" id="yes" onChange={()=>handleOptionChange(item.id, '1')} />
                  <CustomInput value="2" type="radio" id="yes" onChange={()=>handleOptionChange(item.id, '2')} />
               </FormGroup>
          </CardBody>
        </Collapse>
     </Card>
 

Ответ №2:

измените это

 <CustomInput value="1" type="radio" id="yes" onChange={handleOptionChange(item.id, '1')} />
 

в это

 <CustomInput value="1" type="radio" id="yes" onChange={() => handleOptionChange(item.id, '1')} />
 

Причина для причины ,правильно

Для onChange={() => ....} without () => это то же самое, что вы запустите функцию при монтировании компонента, не дожидаясь каких-либо действий пользователя.

Вы можете проверить, предупредив об этом

onChange={() => alert('will run only when user change')}

onChange={alert('Will not wait for user and run when component mount')}

Комментарии:

1. Когда я это делаю, функция handleOptionChange не вызывается при нажатии переключателей, и значения радио не установлены в состояние. Я могу заметить, что переключатели нажимаются неправильно.

Ответ №3:

Событие JavaScript отобразится до ближайшего родителя, у которого есть прослушиватель событий для события

Таким образом, в этом случае, когда вы нажимаете на переключатель, он фактически запускает событие onClick, которое отображается в прослушивателе событий onClick компонента вашей карты, вызывая, таким образом, функцию onClick setToggleValue

Вы можете добавить a onClick={(event)=>event.stopPropagation()} в свой компонент CustomIInput, чтобы предотвратить такое поведение

Комментарии:

1. Я получаю ошибку «событие устарело» со словом «событие», зачеркнутым в VSCode.

2. Извините, это должно быть <код>onClick={(событие)=<код>>event.stopPropagation()}<код>></код>

3. Это должно решить проблему свертывания карты, а два других ответа должны решить проблему неправильного значения

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