问题描述
我有一个驻留在商店中的数组,我们称之为 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)