Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

178
Views
¿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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!