Tengo una función de mapa que muestra elementos:
{data.map((item, index) => ())}Dentro de esta función, me gustaría tener un onClick que muestre condicionalmente un estado de carga cuando la carga sea verdadera.
const [loading, setLoading] = useState(false) {data.map((item, index) => ( <span onClick={() => handleDelete()}> {loading ? ( <LoadingSpinner /> ) : ( <TrashIcon />)} </span> ))}Cuando hago esto, hace que todos los elementos de la lista muestren el estado de carga, no solo el elemento en el que se hizo clic.
¿Hay alguna manera de lograr esto usando el índice?
Todos los elementos de su mapa están escuchando un solo valor de estado booleano; en cambio, puede realizar un seguimiento del índice del elemento en el que se hizo clic o, si desea poder hacer clic y mostrar el estado de carga de varios elementos, puede usar una matriz o Establecer.
A continuación se muestra un enfoque utilizando Set
const [loadingIndices, setLoadingIndices] = useState(new Set()); {data.map((item, index) => ( <span onClick={() => handleDelete(index)}> {loadingIndices.has(index) ? ( <LoadingSpinner /> ) : ( <TrashIcon />)} </span> ))}Ahora, en su función handleDelete, puede agregar el índice del elemento en el que se hizo clic al estado establecido.
handleDelete = (selectedIndex) => { setLoadingIndices((prev) => new Set([...prev, selectedIndex])); // ... // ... // And to remove the element from loading state setLoadingIndices((prev) => { const updated = new Set(prev); updated.delete(selectedIndex); return updated; }); };Debe mover su estado a los elementos en lugar del padre. Actualizar el estado dentro del componente principal hará que todos los elementos secundarios se vuelvan a renderizar.
const childComponent = (props) => { // you can pass the main loading state as a starting point const [loading,setLoading] = useState(props.loading) // initial loader state if(loading) return <LoadingSpinner /> return ( <button onClick={()=> setLoading(prev => !prev)} /> )}luego puede cambiar esto para mostrar diferentes elementos usando declaraciones if como las anteriores.
Si no le importa volver a renderizar los niños, puede usar esta lógica de índice.
const [loading, setLoading] = useState(null); const handleDelete = (index) => { setLoading(index); } {data.map((item, index) => ( <span onClick={() => handleDelete(index)}> {loading === index ? ( <LoadingSpinner /> ) : ( <TrashIcon />)} </span> ))}