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>Funciona según lo previsto, pero cuando uso el botón de radio para elegir una opción en cualquiera de estas tarjetas, automáticamente contrae la tarjeta actual y expande la primera tarjeta. La función handleOptionChange que se activa al hacer una selección de botón de radio también cambia un valor diferente en el estado usando useState:
const handleOptionChange = (name, value) => () => { const Item = name; const numericValue = Number(value); setFormData({ ...data, id: Item, vote: numericValue, }); };handleOptionChange(item.id, '1') no debe llamarse directamente 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>cambia esto
<CustomInput value="1" type="radio" id="yes" onChange={handleOptionChange(item.id, '1')} />dentro de esto
<CustomInput value="1" type="radio" id="yes" onChange={() => handleOptionChange(item.id, '1')} />Motivo de la causa, propiamente
Para onChange={() => ....} sin () => es lo mismo, ejecutará la función cuando se monte el componente sin esperar ninguna acción del usuario.
Puedes probar alertando
onChange={() => alert('will run only when user change')}
...
onChange={alert('Will not wait for user and run when component mount')}
El evento de JavaScript aparecerá en el padre más cercano que tenga un detector de eventos para el evento.
Entonces, en este caso, cuando hace clic en el botón de opción, en realidad desencadena un evento onClick que aparece en el detector de eventos onClick de su componente Card, llamando así a la función onClick setToggleValue
Puede agregar un onClick={(event)=>event.stopPropagation()} a su componente CustomIInput para evitar este comportamiento