I would like to pass all the redux state into an easy to manage key on my props (I'm doing the same with the action creators). I would de-structure the state off the props that I actually need in the components that would consume them. Would the following create performance problems?
const mapStateToProps = (state, ownProps) => ({ reduxState: {...state}})
Inside my component I would destructure the state to consume like:
const {
geosuggestLocation,
mapLocationDetails,
userWants,
smartySuggestion,
geocodeAddress
} = this.props.reduxState
So far, everything works as expected, I would just like to know if it's a pattern I can continue to use without performance issues later down the road.
Related
I want to select an entire slice in redux like the following:
interface AuthState {
user?: User;
shouldShowLogin: boolean;
}
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setUser: ...,
showLogin: ...,
hideLogin: ...,
},
});
export const useAuth = () => useSelector((state) => state.auth);
So I could do something like const { user, shouldShowLogin } = useAuth(); within components. This is handier in most cases but I'm not sure if it's bad practice/inefficient.
I want to do something similar for dispatch (i.e. abstract away useDispatch()). Maybe something like const setUserWithDispatch = (info) => useDispatch()(info); so I can do simply setUserWithDispatch(userInfo) in my components, without having to do useDispatch() and then dispatch(setUser(userInfo)).
Ideally, I'd like to do const { user, shouldShowLogin, setUser, showLogin, hideLogin } = useAuth(); but I'm not sure how to go about it. Again, is this bad practice/inefficient? Why doesn't redux configure this automatically?
The component will rerender when the value selected from useSelector changes. Consequently, you generally want to select the minimum amount of information that you need in order to minimize rerenders.
If there are multiple properties in state.auth and you only care about one then the downside to this destructuring approach is that it will cause the component to rerender when other properties of the object change. In your example you seem to be using all of the properties so it shouldn’t matter.
I think you will have a hard time doing something custom with dispatch without violating the rules of hooks. Hooks cannot be called conditionally and must be called at the top level of the component. You cannot call useDispatch (or a custom hook that uses it) inside of an event handler callback, inside a useEffect function, etc.
The current implementation of the useDispatch hook means that you call useDispatch once per component to get access to the dispatch function for the current store based on the react-redux context. The returned dispatch function is a pure function (not a hook) and can be used anywhere.
You could use redux’s bindActionCreators to bind actions to the dispatch for a particular store instance. This sounds like what you are trying to do, but it is advised against. The downside is that you create an unnecessary coupling between the actions and a particular store instance. You would lose the ability to use a different store instance for testing.
I need to call an action in mapStateToProps, how can I have it?
const mapDispatchToProps = {
someAction,
};
const mapStateToProps = (state, props) => ({
globalParameters: 'some code goes here ...',
relatedDropDownValue: someAction({SOME_TYPE}),
});
The real code is more complicated but I simplified it.
I need to call someAction but I don't know how to get it in mapStateToProps. Is it possible at all?
mapStateToProps is not the place to dispatch actions, rather just to map some state from redux store to the props in your component.
The logic should be refactored as such that the component can decide on what action to dispatch (i.e. useEffect).
So the component must have enough data from the store, to decide what parameters should be given to the action to dispatch.
If there is a need to fetch data, the component should decide to do that, just keep in mind that whatever you wanted to do in the mapStateToProps, should be moved into the component and be dealt with.
Is there a way to typecheck only the substate for the container?
This is how I'm doing it right now:
const mapStateToProps = (state: rootStateType) => (state.subState);
I'd like to avoid creating a dependency between my rootReducer and all containers just for typechecking purposes. I think it makes sense that each container is only concerned with its own subState and typechecks that.
I had an idea of doing the following instead, but to my understanding it will not typecheck the destructured object, but typecheck before destructuring happens.
const mapStateToProps = ({subState}: subStateType) => (subState);
Any ideas? Not really sure what the convention is, maybe it's just simply better to typecheck the whole state in each container.
It's common in redux applications to decouple components from state by using selectors, functions that return a slice of state or computed value from state.
In your case, if you had a selector like
const getSubState = (state): subStateType => state.subState;
Then you could use it with mapStateToProps, and the slice of state would be typed accordingly. You can keep these selectors in the same module as your reducers and import them into your components.
const mapStateToProps = state => getSubState(state);
I'm using React Native and Redux to create an app that helps users find nearby fast-foods. I've got two components : Map and Settings.
Each component is connected (via react-redux) to its respective piece of state. Map can also dispatch an action creator called apiCall :
Map Component
...
connect(
({ map }) => ({ map }),
{ apiCall }
)(Map)
Settings Component
...
connect(
({ settings }) => ({ settings })
)(Settings)
I would like the action creator apiCall to read values from both map and settings pieces of state : this.props.apiCall(map, settings).
However, I want to avoid connecting my Map component to state.settings because it would re-render each time state.settings updates.
I'm still quite confused and have not found "the right approach" in solving this issue. These are the things I tried :
Connecting Map to state.settings and using shouldComponentUpdate() to prevent useless re-renders
Using getState() from the action creator to read state.settings value
Encapsulating everything in another higher component and then passing down specific props
The first two worked but seemed a bit anti-pattern and the third one was still triggering re-renders. Not quite sure why even though it felt like a good solution. I have not tried selectors yet but it seems to be another alternative.
To sum up, my question is :
How to dispatch an action that needs to read values from different pieces of state while avoiding unnecessary re-renders ?
You should use redux-thunk. That way you can return a function (a thunk) in your action creator, which will have access to state
const apiCall = (apiCallArgs) => {
return (dispatch, getState) => {
let mapState = getState('map');
let settingsState = getState('settings');
return dispatch(yourApiAction);
}
}
I have come across this piece of code while learning react-redux
export const mapDispatchToProps = (dispatch, getState) => {
return ActionCreators({completeDriver}, dispatch, getState);
};
I want to know when to use this function.
as per redux actions are dispatched like dispatch(actionCreator())
for doing so inside an react component you need the reference of dispatch which need to be passed as prop to your component.
so if you use connect() you can reduce this passing of dispatch as prop by yourself this thing will be handed via connect HOC(Higher Order Component).
for larger scale application using mapDispatchToProps of connect would saves lot of dev time of wiring things.