Me gustaría clasificar una serie de objetos. Pero estoy atrapado aquí por un tiempo: cuando los accesorios filterActivated cambian, el estado se actualiza (verificado en la herramienta de desarrollo de reacción del navegador), pero no hay re-renderizado.

No entiendo por qué no se vuelve a renderizar la vista, incluso cuando se actualiza ideasArray.

Este es mi componente:

import React, { useState, useEffect } from 'react'

// Components
import Idea from './Idea'

const IdeasContainer = ({ filterActivated }) => {

    const [ideasArray, setIdeasArray] = useState([]);

    useEffect(() => {
        const getIdeas = async () => {
            try {
                const response = await fetch("http://localhost:3004/api/ideas")
                const data = await response.json()
                setIdeasArray(data)
            } catch (err) {
                console.error('getIdeas error: ', err, err.stack)
            }
        }
        getIdeas();
    }, []);

    useEffect(() => {
        const sorted = (array) => {
            let newArray = array.sort(function (a, b) {
                if (filterActivated === 'scoreAsc') {
                    return a.score - b.score
                }
                else if (filterActivated === 'scoreDesc') {
                    return b.score - a.score
                }
            });
            setIdeasArray(newArray);
        }
        sorted(ideasArray);
    }, [filterActivated, ideasArray]);

    return (
        <div className="ideasContainer">
            {
                ideasArray.map((idea, index) => {
                    return <Idea key={index} dataIdea={idea} />
                })
            }
        </div>
    )
}

export default IdeasContainer;

0
Baudoin Michael 3 ago. 2020 a las 23:51

1 respuesta

La mejor respuesta

En primer lugar, tu useEffect tiene algunos problemas:

No haga referencia a ideasArray como una dependencia useEffect si está configurando ese valor dentro de useEffect. Eso causará bucles infinitos porque cuando establece el valor, el `useEffect se llama nuevamente, que establece el valor, que lo llama de nuevo, que establece el valor ... y así sucesivamente. Si depende del valor anterior para establecer el nuevo valor, pase una función de establecimiento a la función setIdeasArray, por ejemplo:

useEffect(() => {
  setIdeasArray(oldValue =>
    [...oldValue].sort((a, b) => {
      if (filterActivated === "scoreAsc") {
        return a.score - b.score;
      } else if (filterActivated === "scoreDesc") {
        return b.score - a.score;
      }
    })
  );
}, [filterActivated]);

Observe cómo también estoy extendiendo el oldValue en una nueva matriz antes de ordenar. Esto se debe a que Array.sort no es confiablemente inmutable, por lo que en ciertas situaciones mutará los datos originales, lo que no queremos en React.


Si el estado cambia, siempre hay una nueva renderización. El ciclo de renderizado de React no es lo mismo que el cambio de DOM, pero React seguirá ejecutando el ciclo de renderizado del componente si los accesorios o el estado cambian.

El problema que tienes se debe al uso de index como key para cada idea. Usar índices como claves es realmente una mala idea.

El objetivo de las claves es permitir que React identifique elementos en una matriz sin tener que volver a representarlos, por lo que al usar los índices, lo que básicamente está diciendo es que el primer elemento (siempre index 0) nunca cambia. Sí, su estado se reordena, pero React ve que las claves no han cambiado de orden, por lo que no cambia el DOM para que coincida.

Las claves deben estar relacionadas con el elemento (como una identificación única), de modo que React pueda identificar ese elemento por algo que no esté relacionado con "su posición dentro de una matriz".

0
JMadelaine 3 ago. 2020 a las 21:33