Gracias por todos sus comentarios y observaciones útiles. siguiendo sus consejos, encuentre a continuación un enlace de sandbox de código
https://codesandbox.io/s/magical-butterfly-uk0fjq?file=/src/item.js
que puede ayudarle a resolver el problema. Todo salta a la vista en la console , con múltiples logs, lo que, dada la escala actual del ejemplo, no plantea ningún problema de rendimiento, pero que podría hacerlo si hubiera una larga lista de elementos.
Entonces, la pregunta es cómo proceder para evitar que los elementos que no se eliminan se vuelvan a procesar, a pesar del hecho de que el padre ( ItemList ) se vuelve a procesar.
La console muestra la representación del Item .
Como se indicó anteriormente, he usado una combinación useMemo + useCallback , pero el resultado resultó ser inestable.
Espero que este ejemplo ayude y sea más explícito.
EDITAR
con respecto al log de la console , extrañamente, el ejemplo de sandbox registra 2 veces App , 2 veces ItemList y 12 veces Item , mientras que en la computadora registra solo 1-1-6 veces
Por lo tanto, si desea minimizar las re-renderizaciones de los elementos, debe asegurarse de algunas cosas
Puede usar React.memo en el componente que desee, lo que evitará que se vuelvan a renderizar cuando los accesorios/estado no cambien.
entonces, usa
export default React.memo(Item);en vez de
export default Item; Cuando representas el componente Item , pasas deleteItem como accesorio con un valor que se recibe del componente App . Sin embargo, esta función no es estable (se redefine cada vez que se procesa el componente de la aplicación. Y dado que la App mantiene el estado de los items , se volverá a procesar después de cada eliminación. Esto activará la deleteItem de un nuevo elemento de eliminación y provocará la Item para volver a renderizar.
Para hacer esto estable, necesitas dos cosas.
React.useCallback que reutiliza la misma función cuando sus dependencias siguen siendo las mismas.function de setItemsentonces, en lugar de
const deleteItem = (newItem) => { const newItemList = items.filter( (item) => item.reference !== newItem.reference ); setItems(newItemList); };usar
const deleteItem = React.useCallback((itemToDelete) => { setItems((currentItems) => currentItems.filter((item) => item.reference !== itemToDelete.reference) ); }, []); También tiene un problema en su código, donde .map los datos pero luego, antes de devolver cada Item , lo empuja en una matriz y lo devuelve en su lugar. Simplemente devuelva el <Item ..>
Entonces, en lugar de
{props.data.map((item, index) => { const newList = []; newList.push( <Item deleteItem={props.deleteItem} key={item.reference} item={item} ></Item> ); return newList; })}hacer
{props.data.map((item, index) => { return ( <Item deleteItem={props.deleteItem} key={item.reference} item={item} ></Item> ); })}Codesandbox actualizado con todos los cambios: https://codesandbox.io/s/twilight-water-9iyobx
Parece que desea iterar sobre su matriz de objetos para producir filas de datos en una tabla con la última celda de cada fila como un botón "eliminar" que elimina la fila. Y puedes hacer eso. No hay necesidad de useEffect .
const { useState } = React; // Pass in the data function Example({ data }) { // Set the state with the data const [ tableData, setTableData ] = useState(data); // When a remove button is clicked `filter` // out those rows that don't match the row id // and reset the state function handleRemove(e) { const { id } = e.target.closest('tr').dataset; const filtered = tableData.filter(obj => { return obj.name !== id; }); setTableData(filtered); } // Create some rows by mapping over the // table data return ( <table> {tableData.map(row => { return ( <Row key={row.name} row={row} handleRemove={handleRemove} /> ); })} </table> ); } // Create a table row and populate the cells // with the information from the row object function Row({ row, handleRemove }) { return ( <tr data-id={row.name}> <td>{row.name}</td> <td>{row.reference}</td> <td>{row.description}</td> <td> <button onClick={handleRemove} >Remove </button> </td> </tr> ); } const data = [ {name: "NAME 1", reference: "REF 1", description: "LOREM IPSUM"}, {name: "NAME 2", reference: "REF 2", description: "LOREM IPSUM"}, {name: "NAME 3", reference: "REF 3", description: "LOREM IPSUM"}, {name: "NAME 4", reference: "REF 4", description: "LOREM IPSUM"}, {name: "NAME 5", reference: "REF 5", description: "LOREM IPSUM"} ]; ReactDOM.render( <Example data={data} />, document.getElementById('react') ); table { border-collapse: collapse; border: 1px solid #565656; } td { border: 1px solid #dfdfdf; padding: 0.5em;} <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="react"></div>Al actualizar el estado, primero debe difundir el estado anterior antes de actualizarlo. Ejemplo:
const deleteItem = (newItem) => { const newItemList = items.filter(item => item.reference !== newItem.reference); setItems(prev => (...prev, newItemList)); }