Reputation: 13296
In redux I want to show a modal if a specific reducer state changes. It is only relevant if the user is viewing a specific component. I used the container's mapDispatchToProps (publishState comes from a reducer):
const mapDispatchToProps = (stateProps, dispatchProps, ownProps) => {
const {dispatch} = dispatchProps;
const {appType, publishState, publishStages} = stateProps;
const isWebsite = (appType !== 'MOBILE');
switch (publishState.stage) {
case publishStages.GENERATING_BUILDREQUEST:
case publishStages.WAITING:
case publishStages.WORKING:
case publishStages.UPLOADING:
dispatch(showModal(modalTypes.PUBLISH_MODAL, {isWebsite}));
break;
case publishStages.COMPLETED:
dispatch(showModal(modalTypes.PUBLISH_SUCCESS_MODAL, {isWebsite}));
break;
case publishStages.ERROR:
dispatch(showModal(modalTypes.PUBLISH_FAILURE_MODAL, {isWebsite}));
break;
default:
dispatch(closeModal());
}
return {...
However this doesn't feel elegant as one wouldn't expect a mapping function to tweak state. Any ideas how to properly achieve this?
Upvotes: 1
Views: 225
Reputation: 15325
I wouldn't indeed call dispatch in the mapDispatchToProps function. This function should be "pure" and just return a mapping without any side effect.
Since you know what action should trigger the modal ie. when publicStages
is set to a particular value, I would suggest taking care of changing the state in 2 possible ways:
publicStages
, the reducer also has access to the modal state, and changes it too. publicStages
. Be mindful that calling dispatch is supposed to be async. In this case, you also need to dispatch from the action, so you have to pass the dispatch function down to the action. EDIT: following the discussion in the comments - and for completeness - if the modal is displayed only as part of one visual component, you could also store its open/closed
state in the component itself and manage it in componentWillMount
and componentWillUpdate
. An interesting read about that from Redux's creator Dan Abramov is You Might Not Need Redux
Upvotes: 3