полученные данные отличаются от старых, но кажутся точно такими же - PullRequest
0 голосов
/ 04 августа 2020

У меня есть MongoDB с Express, который обслуживает данные на конечной точке, к которой обращается React useEffect:

function App() { 
    // const [responsive, setResponsive] = useState("vertical");
    // const [tableBodyHeight, setTableBodyHeight] = useState("100%");
    const [data, setData] = useState([]);
    const [columns, setColumns] = useState([]);

    // const options =  {   
    //     filter:true,
    //     filterType:'dropdown',
    //     responsive,
    // }   

    // Fetch data / headers from express server 
    useEffect(() => {
        const fetchData = async () => {
            const resp = await fetch('http://localhost:4000/todos/');
            const respData = await resp.json();
            
            // Filter out irrelevant data
            const keysToFilterOut = ['_id', '__v']
            const firstDatum = respData[0]; 
            const filteredDatum = _.omit(firstDatum, keysToFilterOut);
            const filteredColumns = Object.keys(filteredDatum);

            setData(respData);
            setColumns(filteredColumns);
        };  
        fetchData()
    }, [data]);

Ловушка useEffect вызывается все время, что означает data как-то всегда меняется. Действительно, я проверил это, добавив эти 3 строки к хуку:

console.log(data === respData);
console.log(data);
console.log(respData);

, а в первом журнале консоли действительно false. Я не понимаю, так как сервер не менял данные, и, кроме того, я посмотрел 2 других журнала консоли - они кажутся идентичными. Почему данные отличаются и как это исправить?

Вот пример из журнала консоли моего приложения:

введите описание изображения здесь

Ответы [ 3 ]

3 голосов
/ 04 августа 2020

Потому что в JS:

примитивы, такие как строки и числа, сравниваются по их значению, в то время как объекты, такие как массивы, даты и простые объекты, сравниваются по их ссылке.

, и поскольку эти 2 объекта являются двумя разными объектами, они не имеют одинаковых ссылок

2 голосов
/ 04 августа 2020

Здесь нужно обсудить две вещи -

Infinite L oop

Когда состояние упоминается в массиве зависимостей useEffect, и мы пытаемся обновить состояние внутри этого без каких-либо предотвращающих условий это приводит к бесконечному l oop. useEffect -> state update -> useEffect, и это продолжается.

Shallow Comparison

React useEffect сравнивает массив зависимостей, чтобы проверить, есть ли обратный вызов необходимо вызвать.

Однако, если объект упоминается в массиве зависимостей, который обновляется при каждой визуализации, даже если их свойства не изменяются, они будут сравниваться по ссылке, и будет вызван эффект, как в ваше дело.

Проблему решает Кент C. Доддса, и он представил альтернативный хук для useEffect - useDeepCompareEffect.

Использование в точности похоже на useEffect, и это будет именно то, на что похоже. Он вызовет обратный вызов только после глубокого сравнения объекта в массиве зависимостей.

Для получения дополнительных сведений ознакомьтесь с этой ссылкой .

0 голосов
/ 04 августа 2020

Вероятно, потому что, как упоминал @ Berto99, объекты сравниваются по ссылке. Что вы можете сделать, так это преобразовать оба объекта в строки, а затем сравнить их.

JSON.stringify(data) === JSON.stringify(respData); // true

Это не самый безопасный вариант, но для простых объектов он должен работать. Я позволяю вам решить, достаточно ли он хорош.

...