Si entiendo correctamente, si se proporciona una clave única para cada elemento de la lista, siempre que agreguemos elementos nuevos o eliminemos elementos existentes, los restantes se volverán a representar. Sin embargo, estoy usando una clave única para el elemento Elemento y cuando hago clic en el botón Agregar , sigo viendo la cadena de representación (agregué un archivo console.log() en el componente Elemento ) que se imprimió en la consola X veces ( x es igual al número total de elementos de la lista).
El código completo es el siguiente:
import "./styles.css"; import { v4 as uuidv4 } from "uuid"; import { useState } from "react"; const data = () => { let result = []; for (let i = 0; i < 10; i++) { result.push({ id: uuidv4(), value: i + 1 }); } return result; }; function Item({ item }) { console.log("render"); return ( <li> <label>{item.value}</label> </li> ); } export default function App() { const [state, setState] = useState(data()); function handleAdd(e) { setState([ ...state, { id: uuidv4(), value: state[state.length - 1].value + 1 } ]); } return ( <div className="App"> <button onClick={handleAdd}>Add</button> {state.map((item) => ( <Item item={item} key={item.id} /> ))} </div> ); }Enlace de CodeSandbox: https://codesandbox.io/s/react-list-with-unique-key-1rxlhx?file=/src/App.js:0-802
¿Me perdí algo aquí?
Las claves no impiden que los niños vuelvan a renderizar; más bien, permiten una "reconciliación" más eficiente , al cambiar solo el nodo DOM subyacente que coincide con esa clave cuando es necesario. El elemento secundario aún se volverá a renderizar en React independientemente, pero si la representación del elemento secundario da como resultado un marcado diferente, la clave se usará para determinar de manera eficiente qué elementos DOM correspondientes a esa clave deben cambiarse, en lugar de cambiar todo . .
Si desea evitar que se vuelva a renderizar, eso requiere una herramienta diferente: React.memo a menudo funciona para componentes individuales. Sin embargo, para listas dinámicas como estas, puede poner el componente en estado.
const { useState } = React; const data = () => { let result = []; for (let i = 0; i < 10; i++) { result.push({ id: Math.random(), value: i + 1 }); } return result; }; function Item({ item }) { console.log("render"); return ( <li> <label>{item.value}</label> </li> ); } function App() { const [items, setItems] = useState(() => data().map(dataObj => <Item item={dataObj} />)); function handleAdd(e) { setItems([ ...items, <Item item={{ id: Math.random(), value: items.length + 1 }} /> ]); } return ( <div className="App"> <button onClick={handleAdd}>Add</button> {items} </div> ); } ReactDOM.render(<App />, document.querySelector('.react')); <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class='react'></div>