Estoy tratando de permitir que los usuarios eliminen valores de la configuración actual.
Tengo una serie de valores que los usuarios pueden tener para las configuraciones que se muestran en un formato de píldora en el que pueden hacer clic en X para eliminar, es decir,
export default function Pill({ value, handleChange }) { // const [times, setTimes] = useState([]); return ( <div className="bg-gray-600 text-white text-xs px-2 py-0.5 w-max-content rounded-lg align-middle mr-1 mb-1"> {value} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="inline-block align-middle cursor-pointer" onClick={() => handleChange(value, "remove")} > <line x1="18" y1="6" x2="6" y2="18" /> <line x1="6" y1="6" x2="18" y2="18" /> </svg> </div> ); }Esto se usa como un componente como se muestra a continuación,
{substanceDetails && substanceDetails.map((subst) => ( <Pill registerInput={register} optionLabel="substance" value={subst.substance} key={subst.substance} optionName="substance" allOptions={["Dexamphetamine", "Ritalin"]} handleChange={handleChange} /> ))}Dado el cambio de identificador, que debe cambiarse, pero se vería así,
const handleChange = (value, mode) => { let updatedValues = values; if (mode === 'remove') { updatedValues = values.filter((elem) => elem !== value); } else if (!updatedValues.includes(value)) updatedValues = [...values, value]; setValues(updatedvalues); }; Estás mutando el estado en tu función handleChange :
const handleChange = (value, mode) => { let updatedValues = values; //takes the reference to state variable if (mode === 'remove') { updatedValues = values.filter((elem) => elem !== value); //mutation } else if (!updatedValues.includes(value)) updatedValues = [...values, value]; setValues(updatedvalues); };Puedes usar algo como esto:
const handleChange = (value, mode) => { if(mode==="remove") setValues(vals => vals.includes(value) ? vals.filter(v => v !== value) : [...vals, value]) }; .includes() no funcionará como se esperaba si los elementos de su matriz no son valores primitivos. Puede usar .find() o .some() en ese caso:
Ejemplo de filtrado por la duration del campo para simplificar :
const handleChange = (value, mode) => { if(mode==="remove") setValues(vals => vals.find(v=> v.duration === value.duration) ? vals.filter(v => v.duration !== value.duration) : [...vals, value]) };Después de leer su código, descubrí que el problema principal podría no ser el problema de la mutación, pero no manejó muy bien el estado.
Primero, sus detalles de substanceDetails deben almacenarse en el componente YourSubstanceListComponent , no en su componente Pill , algo como esto. Esta es la razón principal por la que su primer enfoque no funciona .
// in YourSubstanceListComponent const YourSubstanceListComponent = () = { const [values, setValues] = useState([]); const handleChange = (value, mode,optionName) => { // Should call `setValues` in this function const newValues = [];// TODO setValues(newValues); } return ( <> {values.map(v => <Pill {...otherPillProps} value={v.substance} />)} </> ) } Luego, su handleChange debe colocarse en YourSubstanceListComponent . La razón por la cual es posible que no desee pasar setValues a su componente Pill .
Lo siguiente es la parte sobre cómo obtener nuevos elementos de valores eliminados. Según los documentos:
No modifican la matriz original. Entonces puede usarlos como en su código y debería funcionar.
Pero encontré algunos problemas más en su código y creo que debería verificarlo nuevamente.
map (cuando la cantidad de elementos no cambia) o filter (cuando la cantidad de elementos cambiará). Rara vez uso otros métodos además del map y el filter en toda mi vida.handleChange actualizada, no veo la variable optionName . ¿De dónde viene? Tal vez no actualizó su componente Pill .