Soy bastante nuevo en React.js, y tengo el problema de que cuando intento asignar una matriz a una lista de componentes con estado de React, todos mis componentes pierden su estado. Mi código:
const { useState, useEffect} = React;
const htmlRoot = document.getElementById('root');
const reactRoot = ReactDOM.createRoot(htmlRoot);
const App = () => {
const Item = (props) => {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount((lastCount) => lastCount + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
return <h1>{props.children + ' ' + count}</h1>;
};
const arr = [1, 2, 3];
const [arrState, setArrState] = useState(arr);
const clickHandler = () => {
setArrState((lastArrState) => [
...lastArrState,
lastArrState.at(-1) + 1,
]);
};
return (
// Unfortunately, Stack Snippets don't support the shorthand form
// of fragments
<React.Fragment>
{arrState.map((num, index) => (
<Item key={index}>{num}</Item>
))}
<button onClick={clickHandler}>Click Me</button>
</React.Fragment>
);
};
reactRoot.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
¿Es esto posible para ellos mantener su estado? Si es así, ¿cómo? Actualizar:
Está creando un nuevo componente de Item cada vez que se llama a su componente de App para renderizar. Dado que los renderizados posteriores utilizan componentes diferentes a los renderizados anteriores, React se deshace de las instancias anteriores y crea otras nuevas con un estado nuevo.
En su lugar, defina su componente Item fuera de la App y luego utilícelo dentro de:
const { useState, useEffect } = React;
const htmlRoot = document.getElementById('root');
const reactRoot = ReactDOM.createRoot(htmlRoot);
const Item = (props) => {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount((lastCount) => lastCount + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
return <h1>{props.children + ' ' + count}</h1>;
};
const App = () => {
const arr = [1, 2, 3];
const [arrState, setArrState] = useState(arr);
const clickHandler = () => {
setArrState((lastArrState) => [
...lastArrState,
lastArrState.at(-1) + 1,
]);
};
return (
// (Sadly, Stack Snippets don't support the shorthand form
// of fragments.)
<React.Fragment>
{arrState.map((num, index) => (
<Item key={index}>{num}</Item>
))}
<button onClick={clickHandler}>Click Me</button>
</React.Fragment>
);
};
reactRoot.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
Por separado, no use index para la key (a menos que la lista sea estática o en constante crecimiento y nunca se reordene; la suya se ajusta a esa última categoría, pero supongo que en algún momento eliminará elementos de ella). Detalles sobre por qué en la documentación y el artículo al que se vincula . En cambio, asegúrese de que las cosas que se enumeran tengan algún tipo de identificador único y reutilizable.