Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

190
Vistas
¿Por qué llamar a una función `setState` actualiza un valor de estado completamente separado?

Tengo un problema en el que una función setState actualiza dos valores de estado separados.

Estoy tratando de hacer una pequeña matriz ordenable de React. El programa debería comportarse así:

  • obtiene datos en el montaje
  • almacena esos datos en ganchos de estado de datos unsortedData y datos displayedData
  • cuando un usuario hace clic en el botón "alternar ordenación", la matriz en los datos displayedData se ordena (usando .sort() )
  • en un segundo clic de "alternar clasificación" debería configurar los displayedData para que tengan el mismo valor que unsortedData , restaurando el orden original

Sin embargo, al hacer clic por primera vez en alternar la ordenación, ordena tanto los datos unsortedData como los datos displayedData , lo que significa que pierdo el orden de los datos originales. Entiendo que podría almacenar su pedido, pero quiero saber por qué estos valores de estado parecen estar acoplados.

Código de trabajo de Stackblitz aquí .
GIF que muestra un problema aquí

No puedo encontrar dónde está sucediendo esto. No puedo ver ninguna referencia de objeto/matriz en curso (me estoy extendiendo para nuevos objetos/matrices).

Código aquí:

 const Test = () => { const [unsortedData, setUnsortedData] = useState([]) const [displayedData, setDisplayedData] = useState([]) const [isSorted, setisSorted] = useState(false) const handleSorting = () => setisSorted(!isSorted) useEffect(() => { if (isSorted === true) setDisplayedData([...unsortedData.sort()]) // sort data if (isSorted === false) setDisplayedData([...unsortedData]) // restore original data order }, [isSorted, unsortedData]) useEffect(() => { const mockData = [3, 9, 6] setUnsortedData([...mockData]) // store original data order in "unsortedData" setDisplayedData([...mockData]) }, []) return ( <div> {displayedData.map(item => item)} <br /> <button onClick={() => handleSorting()}>Toggle sorting</button> </div> ) }
about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

La función .sort muta la matriz, así que cuando haces esto:

 setDisplayedData([...unsortedData.sort()])

Estás mutando datos sin clasificar y luego haciendo una copia de ellos. Dado que mutó la matriz original, ese cambio puede mostrarse en la pantalla cuando el componente se vuelve a renderizar.

Entonces, una solución mínima sería copiar primero y ordenar después:

 setDisplayedData([...unsortedData].sort())

Además, ¿por qué necesito el useEffect? ¿Por qué no puedo simplemente mover el contenido de useEffect (que tiene las declaraciones if) a la función handleSorting?

Moverlo a handleSorting debería ser posible, pero en realidad me gustaría proponer otra opción: tener solo dos estados, los datos sin clasificar y el valor booleano de ordenarlos. Los datos mostrados son entonces un valor calculado basado en esos dos.

 const [unsortedData, setUnsortedData] = useState([3, 9, 6]) // initialize with mock data const [isSorted, setisSorted] = useState(false) const displayedData = useMemo(() => { if (isSorted) { return [...unsortedData].sort(); } else { return unsortedData } }, [unsortedData, isSorted]); const handleSorting = () => setisSorted(!isSorted) // No use useEffect to sort the data // Also no useEffect for the mock data, since i did that when initializing the state

Los beneficios de este enfoque son que

  1. No es necesario hacer un doble render. La versión original establece isSorted, renderiza, luego configura los datos mostrados y vuelve a renderizar
  2. Es imposible tener estados no coincidentes. Por ejemplo, entre el primer y el segundo procesamiento, isSorted es verdadero y, sin embargo, los datos mostrados aún no están ordenados. Pero incluso sin el caso de procesamiento doble, tener varios estados requiere que esté atento a que cada vez que actualice unsortedData o isSorted, también recuerde actualizar los datos mostrados. Eso sucede automáticamente si se trata de un valor calculado en lugar de un estado independiente.
about 4 years ago · Juan Pablo Isaza Denunciar

0

Si desea mostrar una matriz ordenada al usuario solo cuando el usuario presiona el botón, puede usar esta declaración de código (originalmente copiada de la lista de tareas pendientes de vue3 )

 const filters = { none: (data) => [...data], sorted: (data) => [...data].sort((a, b) => a - b), } const Test = () => { const [unsortedData, setUnsortedData] = useState([]) const [currentFilter, setCurrentFilter] = useState('none') useEffect(() => { const mockData = [3, 9, 6] setUnsortedData([...mockData]) }, []) return ( <div> <ul> {/* All magic is going here! */} {filters[currentFilter](unsortedData).map(item => <li key={item}>{item}</li>)} </ul> <br /> <button onClick={() => setCurrentFilter(currentFilter === 'none' ? 'sorted' : 'none')}> Toggle sorting </button> </div> ) }
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda