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.
2 Answers
Reset to default 7What 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条)