如何防止useSelector造成不必要的渲染?

问题描述 投票:0回答:2

我正在使用

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
,但我愿意接受建议,即使它涉及其他库。

javascript reactjs redux react-hooks redux-thunk
2个回答
6
投票

你应该做的不是选择整个状态,而是选择你需要的部分:)

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


0
投票

您可以全局禁用所有选择器

<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]

© www.soinside.com 2019 - 2024. All rights reserved.