Reputation: 3727
I'm creating a notification state like this (in redux),
import { STORE_NOTIF, PURGE_NOTIF } from '../actions/notif';
const defaultState = {
kind: null,
message: null
}
export default function notifReducer(state = defaultState, action) {
switch(action.type) {
case STORE_NOTIF:
return {kind: action.kind, message: action.message};
case PURGE_NOTIF:
return defaultState;
default:
return state;
}
}
this works for events I know to control. But where should I implement the clearing (PURGE_NOTIF) for when I transition to pages, say from sign-in to home page? I don't want to write a componentWillMount
(and I don't think that's the write way) on every component to clear the notifState
. Should this be like somewhere in the routes? I use react-router BTW.
UPDATE with answer
My new reducer looks like this where I added a displayed
boolean
import _ from 'lodash';
import { STORE_NOTIF, PURGE_NOTIF, DISPLAY_NOTIF } from '../actions/notif';
const defaultState = {
kind: null,
message: null,
displayed: true
}
export default function notifReducer(state = defaultState, action) {
switch(action.type) {
case STORE_NOTIF:
return _.merge({}, state, { kind: action.kind, message: action.message, displayed: action.displayImmediately });
case DISPLAY_NOTIF:
return _.merge({}, state, { displayed: true });
case PURGE_NOTIF:
return defaultState;
default:
return state;
}
}
and in my client is where I check if it's been displayed already or not and handle appropriately.
const scrollTop = () => { window.scrollTo(0, 0) }
const handleNotifs = (store) => {
const notifState = store.getState().notifState;
if (notifState.message) {
if (notifState.displayed) {
store.dispatch({type: PURGE_NOTIF});
} else {
store.dispatch({type: DISPLAY_NOTIF});
}
}
}
const store = applyMiddleware(...middlewares)(createStore)(reducer, initialState);
ReactDOM.render(
<Provider store={store}>
<Router onUpdate={() => {scrollTop(); handleNotifs(store)}} routes={routes} history={browserHistory} />
</Provider>,
document.getElementById('app')
);
Upvotes: 3
Views: 6700
Reputation: 12420
If you define your React Router routes using plain route objects, you can define lifecycle events on your route. The simplest way to achieve what you described is to specify onLeave
on the route.
const onLeave = () => store.dispatch({type: "PURGE_NOTIF"})
const routes = (
{path: "/login", component: LoginPage, onLeave}
)
You need to pass a reference to store
to your routes
. Here is a possible solution:
// index.js
const store = createStore(/* ... */)
const routes = createRoutes(store)
ReactDOM.render(
<Provider store={store}>
<Router routes={routes} />
</Provider>
)
// createRoutes.js
export default store => {
const purge = () => store.dispatch({type: "PURGE_NOTIF"})
return (
{path: "/", component: Application, childRoutes: [
{path: "login", component: LoginPage, onLeave: purge},
{path: "dashboard", component: Dashboard},
]}
)
}
Upvotes: 2