我正在使用
useSelector
钩子来检索我的减速器的值,但它导致我的应用程序上出现大量不必要的渲染。
我在组件上使用哪个属性并不重要,因为它们都从减速器获取相同的
state
对象,每次一个属性更改时,都会渲染所有使用 useSelector
的组件。
这是减速机:
const initialState = {
productsDataState: [], // => this is populated by multiple objects
searchProducts: [],
isSearchOn: false,
inputValue: '',
listOrder: [],
toastify: ['green', ''],
toastifyOpen: false
}
const reducer = ((state = initialState, action) => {
switch (action.type) {
case actionTypes.UPDATE_PRODUCT:
return {
...state,
productsDataState: action.products,
listOrder: action.listOrder
}
case actionTypes.SET_TOASTIFY:
return {
...state,
toastify: action.toastify,
toastifyOpen: action.open
}
case actionTypes.SET_SEARCH:
return {
...state,
searchProducts: action.searchProducts,
isSearchOn: action.isSearchOn,
inputValue: action.inputValue
}
default:
return state
}
})
其中一个组件正在使用
isSearchOn
,它是一个布尔值,所以我解决了在渲染之前检查该值是否为 true
的问题:
const { isSearchOn } = useSelector(state => state.isSearchOn && state)
但并非所有组件都是如此。我现在遇到的问题是使用
productsDataState
属性,它是一个对象数组。我不能只在返回之前进行简单的验证state
。我考虑过将初始值存储在 useState
中,在返回状态之前对当前值和过去的值进行深入比较,这与我在其他组件中所做的类似,但我不知道如何这将是一个很好的方法。
const { productsDataState } = useSelector(state => state)
有没有一种方法可以让我在不影响应用程序性能的情况下利用
useSelector
?
我已经阅读了很多书并做了很多测试,但到目前为止我找不到一个好的方法。
我想保留
useSelector
,但我愿意接受建议,即使它涉及其他库。
你应该做的不是选择整个状态,而是选择你需要的部分:)
const productsDataState = useSelector(state => state.productsDataState)
@编辑
如果您想使用一个选择器选择多个数据,例如您尝试使用对象,则会导致它更改引用。
const { productsDataState, other } = useSelector(state => ({ productsDataState: state.productsDataState, other: state.other }))
这将导致任何状态更改时重新渲染,因为 redux 默认情况下使用严格相等检查。
您应该听官方文档并分别选择每个状态
Call useSelector() multiple times, with each call returning a single field value
您可以全局禁用所有选择器:
<Provider store={store} stabilityCheck="never">
<App />
</Provider>
或者您可以为每个选择器禁用它:
const selectItems = useSelector((state: RootState) => state.items,
{
devModeChecks: { stabilityCheck: "never" },
})
了解更多信息:[https://react-redux.js.org/api/hooks#selector-result-stability]