React + Redux - 在商店更改时更新本地状态 => 无限循环

问题描述

我有一个驻留在商店中的数组,我们称之为 users 并且我有一个自定义钩子,可以从商店中检索它(通过 useSelector)。基于 store 中的这个数组,我的组件中有一个本地状态,用作表格的显示源。我需要在本地状态下单独使用它,因为我根据搜索功能过滤数据。

我想要做的是,每当 store 中的数据发生变化时,我也想更新本地状态以反映这些变化(但要事先调用它上面的过滤函数)。

然而,这会导致无限循环,因为 useEffect + setState 会导致重绘,从而再次更改 store 变量等。

const users = useUsers() // uses redux store
const [displayUsers,setdisplayUsers] = useState(users) // local state

useEffect(() => {
   const filteredUsers = onSearch(users) // applies the filtering
   setdisplayUsers(filteredUsers) // updates the local state
},[users])

return <Table source={displayUsers} ... />

有人可以帮忙吗?

解决方法

由于 displayUsers 是从 props 派生的,所以不需要在 state 中维护它。每当 props 发生变化时,即时计算它,如果由于其他原因经常渲染组件,请使用 memo:

const users = useUsers() // uses redux store

const displayUsers = useMemo(() => onSearch(users),[onSearch,users])

return <Table source={displayUsers} ... />

如果您确实需要在 store 更改时设置状态,请确保选择器已记忆 - 即如果没有任何更改,您将获得相同的数组。因此,在重新渲染组件时,选择器将返回相同的 users 数组,这将防止再次调用 useEffect

您可以使用 useSelector(第二个参数)调用 equalityFn 以避免在没有任何更改的情况下返回新值 (see Equality Comparisons and Updates)。这是文档中的示例:

import { shallowEqual,useSelector } from 'react-redux'

const selectedData = useSelector(selectorReturningObject,shallowEqual)