Firing Redux actions in response to route transitions in React Router

前端 未结 2 1174
天命终不由人
天命终不由人 2020-12-22 19:08

I am using react-router and redux in my latest app and I\'m facing a couple of issues relating to state changes required based on the current url params and queries.

2条回答
  •  借酒劲吻你
    2020-12-22 19:25

    As mentioned before, the solution has two parts:

    1) Link the routing information to the state

    For that, all you have to do is to setup react-router-redux. Follow the instructions and you'll be fine.

    After everything is set, you should have a routing state, like this:

    state

    2) Observe routing changes and trigger your actions

    Somewhere in your code you should have something like this now:

    // find this piece of code
    export default function configureStore(initialState) {
        // the logic for configuring your store goes here
        let store = createStore(...);
        // we need to bind the observer to the store <>
    }
    

    What you want to do is to observe changes in the store, so you can dispatch actions when something changes.

    As @deowk mentioned, you can use rx, or you can write your own observer:

    reduxStoreObserver.js

    var currentValue;
    /**
     * Observes changes in the Redux store and calls onChange when the state changes
     * @param store The Redux store
     * @param selector A function that should return what you are observing. Example: (state) => state.routing.locationBeforeTransitions;
     * @param onChange A function called when the observable state changed. Params are store, previousValue and currentValue
     */
    export default function observe(store, selector, onChange) {
        if (!store) throw Error('\'store\' should be truthy');
        if (!selector) throw Error('\'selector\' should be truthy');
        store.subscribe(() => {
            let previousValue = currentValue;
            try {
                currentValue = selector(store.getState());
            }
            catch(ex) {
                // the selector could not get the value. Maybe because of a null reference. Let's assume undefined
                currentValue = undefined;
            }
            if (previousValue !== currentValue) {
                onChange(store, previousValue, currentValue);
            }
        });
    }
    

    Now, all you have to do is to use the reduxStoreObserver.js we just wrote to observe changes:

    import observe from './reduxStoreObserver.js';
    
    export default function configureStore(initialState) {
        // the logic for configuring your store goes here
        let store = createStore(...);
    
        observe(store,
            //if THIS changes, we the CALLBACK will be called
            state => state.routing.locationBeforeTransitions.search, 
            (store, previousValue, currentValue) => console.log('Some property changed from ', previousValue, 'to', currentValue)
        );
    }
    

    The above code makes our function to be called every time locationBeforeTransitions.search changes in the state (as a result of the user navigating). If you want, you can observe que query string and so forth.

    If you want to trigger an action as a result of routing changes, all you have to do is store.dispatch(yourAction) inside the handler.

提交回复
热议问题