I would like to have functions that can get the current state to do some logic with it, without having to pass the current state via parameters to the function.
Here is my example.
In my action file, I have:
export const addToSearchHistory = (newSearch) => ({type: ADD_TO_SEARCH_HISTORY, newSearch})
export const addToCardHistory = (newCard) => ({type: ADD_TO_CARD_HISTORY, newCard})
And for example I would like to have a "getter" function that tells me if the "Search history" has hit 10 items. So what I did is:
export const searchHasMaxHistory = () => (dispatch, getState) => {
var state = getState()
search = state.search
return search.history == 10 ? true : false
}
And I bind this function with the other "real" actions with bindActionCreators:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
addToSearchHistory,
addToCardHistory,
searchHasMaxHistory
}, dispatch)
}
So I'll be accessible as any normal actions. It works well and does exactly what I want.
But the real question is, is it anti-pattern to bind it like an action but it doesn't return an action? May I run into issues or whatsoever by doing that? And is there a "right" solution to do that?
React Redux offers a set of hooks as an alternative to the existing connect() higher-order component. These hooks allow you to connect to the Redux store and dispatch actions without having to wrap your components in connect().
With useSelector() , returning a new object every time will always force a re-render by default. If you want to retrieve multiple values from the store, you can: Call useSelector() multiple times, with each call returning a single field value.
As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.
Reselect provides a function called createSelector to generate memoized selectors. createSelector accepts one or more "input selector" functions, plus an "output selector" function, and returns a new selector function for you to use.
For this, you should bind your "getter" (which is described as a "selector" in the docs) to your component via the mapStateToProps
function.
// the selector (probably in your reducer file)
export const searchHasMaxHistory = state => {
return state.search.history == 10 ? true : false
}
// in your component
const mapStateToProps = (state) => {
return {
hasHitMaxHistory: searchHasMaxHistory(state)
}
}
const mapDispatchToProps = ... // keep the same, remove your "getter"
export default connect(
mapStateToProps,
mapDispatchToProps
)(YourComponent)
This approach makes more sense to me, as your component's new prop will behave as intended, and trigger a render() when the returned value changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With