为什么我的useEffect中仍然有陈旧的数据?

问题描述 投票:1回答:1

我的 useEffect 正在运行,但一旦完成,它就不会更新我的组件的状态。它总是显示之前的渲染。我想我已经添加了所有适当的依赖关系,但它仍然给我陈旧的数据。这是我的钩子。

export default function useSort(items, sortKey, sortAscending) {
  let [sorted, setSorted] = useState(items);

  useEffect(() => {
    let sortedItems = sortKey ? items.sort((a, b) => {
      if (!a[sortKey] && b[sortKey]) return sortAscending ? -1 : 1;
      if (a[sortKey] && !b[sortKey]) return sortAscending ? 1 : -1;
      if (a[sortKey] > b[sortKey]) return sortAscending ? 1 : -1;
      if (a[sortKey] < b[sortKey]) return sortAscending ? -1 : 1;
      return 0;
    }) : items;
     setSorted(sortedItems);
  }, [items, sortKey, sortAscending]);

  return sorted;
}

这是我使用它的组件:

const SearchResults = ({ columns, searchResults, sortAscending, sortKey }) => {
  const dispatch = useDispatch();
  let sorted = useSort(searchResults, sortKey, sortAscending);

  return sorted.map((searchResult, index) => {
    return ( ... )
  }

SearchResult 渲染,但是当我试图对结果进行排序时(取决于我点击的列头),结果是 useEffect 代码运行。经过整理后。SearchResult 从来没有被重新渲染以显示变化。

我是如何错误地使用钩子的?正确的用法是什么?

javascript reactjs react-hooks
1个回答
6
投票

JavaScript中的数组是 reference 类型;以及 setState 会导致当前值和之前值不同的组件重新渲染;与基元类型不同的是,引用类型只有在其引用发生变化时才会被标记为改变(即浅层比较)。在这种情况下,当你在原地突变数组时,从浅层比较的角度来看,前一个值和后一个值是一样的,这就像调用了 setState(2)state 已是 2人们已经在评论中提到,如果你返回新的数组(新的引用),就会解决这个问题;顺便看看下面的片段,看看这里发生的问题的具体例子。

ReactDOM.render(<Test/>, document.getElementById("root"))

function Test(){
    const [array, setArray] = React.useState([2,3,4,5]);
    const renderCounter = React.useRef(0);
    
    function mutateInPlace(e){
        renderCounter.current++;
        // some random in-place mutations
        array[1] = 4;
        array[2] = 11;
        array.sort((a,b)=>a-b);
        setArray(array);
    }
    
    function mutateOutOfPlace(e) {
        renderCounter.current++;
        // creating a new array
        let arrayCopy = array.slice(0);
        setArray(arrayCopy);
    }
    
    console.log("re-rendered");
    return (
        <div>
            {renderCounter.current}
            <br/>
            <button onClick={mutateInPlace}>mutate in-place</button>
            <button onClick={mutateOutOfPlace}>mutate out-of-place</button>
        </div>
    );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="root"></div>
© www.soinside.com 2019 - 2024. All rights reserved.