Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Redux state on route change

I've been trying to figure this out for a while and I'm getting more and more confused.

I want to reset/change Redux state every time I leave or change route. I'm using react-router-redux with history.listener dispatching an action every time route changes

history.listen(location => store.dispatch(resetManualsCategory()));

Action creator:

export function resetManualsCategory() {
    return {
        type: 'RESET_MANUALS_CATEGORY'
    }
}

Reducer

export function manualCategories(state=[], action) {
    switch (action.type) {
        case 'SELECT_MANUALS_CATEGORY':
           [...]

        case 'RESET_MANUALS_CATEGORY':
            console.log('test reducer');
            return Object.assign({}, state, {
                manualCategory: 'test'
            })

        default:
            return state
    }
}

What confuses me the most, the state updates if I refresh the page or click twice on the route in the top nav, but a single route change doesn't affect the redux state even though the action and reducer fire (displays the test message in the console).

What am I doing wrong and what actually is happening here?

like image 971
spik3s Avatar asked Jun 19 '16 19:06

spik3s


2 Answers

react-router-redux provides a LOCATION_CHANGE action, which is already dispatched on every route change. You could do simple:

import { LOCATION_CHANGE } from 'react-router-redux'

export function manualCategories(state=[], action) {
    switch (action.type) {
        case LOCATION_CHANGE:
            /*
              action.payload is something like:
              {
                pathname: '/',
                search: '',
                hash: '',
                state: null,
                action: 'PUSH',
                key: 'xwl8yl',
                query: {},
                $searchBase: {
                  search: '',
                  searchBase: ''
                }
              }
            */

        default:
            return state
    }
}
like image 196
Diego Haz Avatar answered Oct 13 '22 00:10

Diego Haz


Currently I'm making use of componentWillUnmount() to do this. I have an action setup in the reducer I want to reset to reset its state and I dispatch the action from the componentWillUnmount() method.

One issue you may experience with this is that when using React Router a route change will not trigger a refresh and a component will not remount on the same route, so for example if you have a posts/new and a posts/edit/:id route both using the same component to edit a post, going between these routes will not cause the component to remount.

Because of this componentWillUnmount() will NOT run, the same component will just receive new props. Therefore you could use componentWillReceiveProps(newProps) to perform a comparrison and update accordingly.

If you do want to force the component to remount you need to ensure the component you want to remount has a different key attribute, see here and here for more information.

like image 32
tomhughes Avatar answered Oct 13 '22 00:10

tomhughes