Tengo una función .map que muestra datos que se extraen de una API, me gustaría agregar un campo a los datos y hacer que coincida con el dato relevante.
Por ejemplo, estoy extrayendo ingredientes de una API que contiene cantidades, me gustaría agregar un campo de entrada que me permita agregar un multiplicador que luego podría usar para multiplicar los ingredientes.
Aquí está la función .map:
<div className="mt-4 border-t border-b border-gray-200 divide-y divide-gray-200"> {data.ingredients.map((ingredient) => ( <div key={ingredient.id} className="relative flex items-start py-4" > <div className="ml-4 flex items-center h-5"> <input onChange={selectIngredient(ingredient.id)} value={selectedIngredients.indexOf(ingredient.id === -1)} type="checkbox" className="focus:ring-purple-500 h-4 w-4 text-purple-600 border-gray-300 rounded" /> </div> <div className="ml-3 text-sm"> <label className="font-medium text-gray-700 select-none" > {ingredient.name} </label> </div> <div className="ml-3 text-sm"> // Here I am using useState to set a multiplier, but it sets the same vale for all data in the .map list. <input value={multiplier} onChange={(e) => setMultiplier(e.target.value)} type="number" className="flex-1 focus:ring-purple-500 focus:border-purple-500 block w-full min-w-0 rounded-md sm:text-sm border-gray-300" /> </div> </div> ))} </div>Así es como se ve un objeto de ingrediente:
ingredient: { id: 1, name: sugar, quantity: 100, quantityUnit: grams, }¿Hay alguna manera de configurar un estado que esté vinculado a la pieza de datos mapeada relevante?
En su componente, cree un nuevo estado. Llamemos a esto el estado de los ingredients que tiene un despachador setIngredients . Establézcalo por defecto como una matriz vacía.
const [ingredients, setIngredients] = useState([]); Con un gancho useEffect , recorra los datos recibidos con el método .map() y devuelva un nuevo objeto de cada ingrediente con una propiedad de multiply agregada. Actualice el estado de los ingredients con esta nueva matriz de objetos.
useEffect(() => { if (data.length) { setIngredients( data.map(ingredient => ({ ...ingredient, multiply: 1 }) ); } }, [data]); Ahora su estado de ingredients tiene todos los ingredientes más una propiedad de multiply para cada ingrediente.
Solo para estar seguro, agregué este fragmento de (pseudo) código para demostrar cómo debería funcionar la solución.
Cada ingrediente ahora tiene una propiedad de multiply , por defecto establecida en 1 . En su formulario, agrega una nueva entrada que maneja el valor de multiplicación. El usuario puede usar la entrada para cambiar la multiplicación.
Si es necesario, también puede agregar una entrada oculta que rastree la cantidad total de un ingrediente (cantidad * multiplicar). Esto puede ser útil cuando envíe su formulario.
const handleMultiplyChange = (event, id) => { const value = Number(event.value) const updatedIngredients = ingredients.map(ingredient => ({ ...ingredient, multiply: ingredient.id === id ? value : ingredient.multiply })); setIngredients(updatedIngredients); }; return (ingredients.map(ingredient => ( <> <input type="checkbox" name="ingredient" value={ingredient.id} /> <input type="number" name="multiply" min="1" value={ingredient.multiply} onChange={(event) => handleMultiplyChange(event, ingredient.id)} /> <input type="hidden" name="totalQuantity" value={(ingredient.multiply * ingredient.quantity)} /> </> ));