【问题标题】:fetched data is different from old data, but seems exactly the same获取的数据与旧数据不同,但看起来完全一样
【发布时间】:2020-11-23 23:51:24
【问题描述】:

我有一个带有 Express 的 MongoDB,它在端点上提供数据,由 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 个控制台日志 - 它们看起来相同。数据有何不同以及如何修复?

这是我的应用程序控制台日志中的一个示例:

【问题讨论】:

  • 因为Js中对象的相等性不是检查容器值而是检查引用?
  • 也许this 可以帮助您使用 useEffect 挂钩深入比较对象。
  • @himayan 迄今为止的最佳选择。想把它改成答案吗?
  • 当然。请给我一分钟。

标签: javascript reactjs use-effect


【解决方案1】:

因为在 JS 中:

像字符串和数字这样的基元是通过它们的值来比较的,而像数组、日期和普通对象这样的对象是通过它们的引用来比较的。

由于这两个对象是两个不同的对象,它们没有相同的引用

【讨论】:

  • 好的,我可以让useEffect比较值而不是参考吗?
  • @CIsForCookies this answer 可能会帮助你
【解决方案2】:

这里有两件事要讨论-

无限循环

useEffect 的依赖数组中提到了一个状态,并且我们尝试在没有任何阻止条件的情况下更新其中的状态时,它会导致无限循环。 useEffect --> state update --> useEffect 然后继续。

浅比较

React 的useEffect 对依赖数组进行比较以检查是否需要调用回调。

但是,如果在每次渲染时更新的依赖数组中提到了一个对象,即使它们的属性没有改变,它们也会通过引用进行比较并调用效果,就像你的情况一样。

Kent C. Dodds 解决了这个问题,他为useEffect - useDeepCompareEffect 引入了一个替代挂钩。

用法与useEffect 完全相似,并且完全符合听起来的样子。只有在对依赖数组中的对象进行深度比较后才会触发回调。

欲了解更多详情 - 请查看此link

【讨论】:

  • 实际上,这并没有按预期工作,因为现在tableData 始终保持不变,即使 fetch 会产生一个新值,这意味着当数据库更新时,react 不会反映这一点,除非我使用原来的useEffect
  • 重新渲染的根本原因是——更新 useEffect 中的数据,同时将数据作为依赖数组的一部分。你能解释一下用例以及为什么要在依赖数组中使用数据吗?可能有另一种方法可以实现这一点。
【解决方案3】:

可能是因为正如@Berto99 所提到的,对象是通过引用进行比较的。 您可以做的是将两个对象都转换为字符串,然后比较它们,

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

虽然这不是最安全的选择,但对于简单的对象它应该这样做。我让你决定它是否足够好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多