javascript - How to prevent useSelector from causing unnecessary renders? - Stack Overflow

I'm using useSelector hook to retrieve the values of my reducer, but it is causing a lot of unnece

I'm using useSelector hook to retrieve the values of my reducer, but it is causing a lot of unnecessary renders on my application.

It doesn't matter which property I'm using on a ponent, since they are all getting the same state object from the reducer, every time one property changes, all ponents that use useSelector are rendered.

This is the reducer:

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
   }
})

One of the ponents is using isSearchOn, which is a boolean, so I solved the problem checking if the value is true before rendering it:

 const { isSearchOn } = useSelector(state => state.isSearchOn && state)

But that's not the case for all ponents. The one I'm stuck right now uses the productsDataState property, which is an array of objects. I can't just make a simple validation before returning state. I thought about storing the initial value in a useState, make a deep parison between the current value and the past one before returning the state, which would work similarly to what I did in the other ponent, but I can't see how this would be a good approach.

const { productsDataState } = useSelector(state => state)

Is there a way where I could take advantage of useSelector without primising the performance of the application?

I've being reading a lot and making a lot of tests, but I couldn't find a good way to do that so far.

I'd like to keep useSelector, but I'm open to suggestions, even if it involves other libraries.

I'm using useSelector hook to retrieve the values of my reducer, but it is causing a lot of unnecessary renders on my application.

It doesn't matter which property I'm using on a ponent, since they are all getting the same state object from the reducer, every time one property changes, all ponents that use useSelector are rendered.

This is the reducer:

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
   }
})

One of the ponents is using isSearchOn, which is a boolean, so I solved the problem checking if the value is true before rendering it:

 const { isSearchOn } = useSelector(state => state.isSearchOn && state)

But that's not the case for all ponents. The one I'm stuck right now uses the productsDataState property, which is an array of objects. I can't just make a simple validation before returning state. I thought about storing the initial value in a useState, make a deep parison between the current value and the past one before returning the state, which would work similarly to what I did in the other ponent, but I can't see how this would be a good approach.

const { productsDataState } = useSelector(state => state)

Is there a way where I could take advantage of useSelector without primising the performance of the application?

I've being reading a lot and making a lot of tests, but I couldn't find a good way to do that so far.

I'd like to keep useSelector, but I'm open to suggestions, even if it involves other libraries.

Share Improve this question asked Aug 16, 2022 at 21:29 Berg_DurdenBerg_Durden 1,7796 gold badges33 silver badges63 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

What you should be doing is not selecting whole state, just the part you need :)

const productsDataState = useSelector(state => state.productsDataState)

@edit

If you want to select multiple data with one selector you will cause it to change reference if you would try to use an object for example.

const { productsDataState, other } = useSelector(state => ({ productsDataState: state.productsDataState, other: state.other }))

this will cause rerender on any state change as redux use strict equality check by default.

You should listen to official documentation and select each state separately

Call useSelector() multiple times, with each call returning a single field value

You can disable it for all selectors globally:

    <Provider store={store} stabilityCheck="never">
      <App />
    </Provider>

Or you can disable it per selector:

    const selectItems = useSelector(
      (state: RootState) => state.items, 
      { devModeChecks: { stabilityCheck: "never" } }
    )

For more information: Selector result stability

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744265469a4565845.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信