Estoy mostrando mi estado, que es una matriz, recorriéndolo con la función de mapa. Además, tengo un botón que invierte la matriz al hacer clic.
import React, { useState, useEffect } from "react"; import PropTypes from "prop-types"; import "./App.css"; const App = (props) => { const [reverse, setReverse] = useState(false); const [arr, setArr] = useState([]); useEffect(() => { let newArr = props.arr; newArr = newArr.reverse(); setArr(newArr); }, [reverse, props.arr]); return ( <div className="App"> <button onClick={() => { setReverse(!reverse); }} > Reverse </button> {arr.map((e, i) => { return ( <div key={i}> <p>{e}</p> </div> ); })} </div> ); }; App.propTypes = { arr: PropTypes.array, }; export default App;Creo que es bastante obvio lo que quiero hacer. Pero no funciona para mí y no sé por qué. Tengo que hacer clic dos veces para lograr la primera reversión y surge el caso extraño en el que la matriz que se representa y la que se muestra en el estado del componente por las herramientas de desarrollo de React en Chrome no coinciden.
No puedo explicar este comportamiento. Estoy empezando a pensar que tiene algo que ver con el hecho de que obtengo la matriz de los accesorios, pero realmente no lo sé. ¿Algunas ideas?
Hay varias mejoras por hacer. Algunos son errores y otros son simplemente antipatrones.
Lo primero a tener en cuenta es que reverse muta la matriz original. Nunca debes mutar el estado o los accesorios en React.
El segundo es un antipatrón que consiste en copiar accesorios en un estado que no es necesario.
Los documentos de React dicen que el estado es para valores que cambian con el tiempo. Dice que un valor no es un estado si se puede derivar de accesorios.
¿Puede calcularlo en función de cualquier otro estado o accesorios en su componente? Si es así, no es estatal.
Eso es lo que tenemos en este caso.
En lugar de copiar el prop arr en estado e invertirlo allí, podemos usar el prop y una variable temporal para lograr el mismo objetivo con menos código.
const {useState, useEffect} = React; const App = (props) => { const [reverse, setReverse] = useState(false); let array = [...props.arr]; // New reference so we will not mutate props if (reverse) { array.reverse(); } return ( <div className="App"> <button onClick={() => { setReverse(!reverse); }} > Reverse </button> {array.map((e, i) => { return ( <div key={i}> <p>{e}</p> </div> ); })} </div> ); }; ReactDOM.render(<App arr={[1,2,3]} />, document.getElementById('root')); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>El principal error es que está asignando sus accesorios a la variable newArr , no a arr , por lo que cada vez no es el nuevo estado de arr el que se invierte, sino la matriz original de props . Además, al cambiar los props , es mejor agregar un useEffect más. He proporcionado un ejemplo del código correcto a continuación . Pido disculpas si hay errores, no hablo bien inglés.
useEffect(() => { setArr(props.arr); }, [props.arr]); useEffect(() => { if (!arr.length) return; let newArr = arr.length ? [...arr] : [...props.arr]; newArr = [...newArr.reverse()]; setArr(newArr); }, [reverse]);Esto se debe a que el gancho useEffect() se ejecuta en el montaje de su componente e invierte su matriz aunque no haya hecho clic en el botón de retroceso.
Intente agregar lógica para evitar la primera inversión que está ocurriendo en la montura.
Esto probablemente funcionaría para ti,
useEffect(() => { if(arr.length>0){ let newArr = props.arr; newArr = newArr.reverse(); setArr(newArr); } }, [reverse, props.arr]);