Chciałbym sortować szereg obiektów. Ale utknęłam tu na chwilę: Gdy zmiany filterActivated, stan jest aktualizowany (zweryfikowany w narzędziu Dev Reaction Browser), ale nie ma renderowania.

Nie rozumiem, dlaczego widok nie jest ponownie renderowany, nawet gdy ideasArray jest aktualizowany.

To jest mój komponent:

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 sierpień 2020, 23:51

1 odpowiedź

Najlepsza odpowiedź

Po pierwsze, twoje useEffect ma kilka problemów:

Nie odwołuj się do ideiArray jako zależności useEffect, jeśli ustawienie tej wartości wewnątrz useEffect. To spowoduje nieskończone pętle, ponieważ po ustawieniu wartości, `Useffect zostanie ponownie wywołany, który ustawia wartość, która go ponownie nazywa, co ustawia wartość ... i tak dalej. Jeśli polegasz na poprzedniej wartości, aby ustawić nową wartość, przejdź funkcję settera do funkcji SetiveArray, na przykład:

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]);

Zauważ, jak również rozprzestrzeniaj się oldValue do nowej tablicy przed sortowaniem. Dzieje się tak, ponieważ Array.sort nie jest niezmiennie niezmienna, więc w pewnych sytuacjach zmutują oryginalne dane, których nie chcemy w reakcji.


Jeśli zmienia się stan, zawsze istnieje render. Cykl reakcji reakcji nie jest taki sam jak zmiana Domu, ale reaguje nadal uruchomi cykl renderowania komponentu, jeśli rekwizyty lub zmiany stanu.

Problem, który masz, jest spowodowany użyciem index jako key dla każdego pomysłu. Korzystanie z indeksów jako kluczy jest naprawdę zły pomysł.

Cały punkt kluczy jest zezwolenie na reagowanie na identyfikację elementów w tablicy bez konieczności ponownego renderowania, więc za pomocą indeksów, co zasadniczo mówiąc, jest to, że pierwszy przedmiot (zawsze indeks {x0}}) nigdy się nie zmienia. Tak, twój stan jest ponownie zamówiony, ale reaguje widzi, że klucze nie zmieniły zamówienia, więc nie zmienia dom do dopasowania.

Klucze muszą być związane z przedmiotem (np. Unikalny identyfikator), dzięki czemu reaguje może zidentyfikować ten przedmiot przez coś niepowiązanego z "jego pozycją w tablicy".

0
JMadelaine 3 sierpień 2020, 21:33