Skip to content

Instantly share code, notes, and snippets.

@andrerpena
Created June 19, 2016 14:12
Show Gist options
  • Save andrerpena/aa2facb0094c229da8257c8e9512dba2 to your computer and use it in GitHub Desktop.
Save andrerpena/aa2facb0094c229da8257c8e9512dba2 to your computer and use it in GitHub Desktop.
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);
}
});
}
@andrerpena
Copy link
Author

One recurring question that I see in the Redux world is:

How do I trigger an Action as a response to changes in the route?

This is a popular question because it's a common use-case to have your state bound to the route. Consider this sample URL:

 www.acne.com/cars?model=ModelS //Consider the user selects the model from a dropdown

Now, because model=ModelS, you might have a state called carModel which contains lots of information about the car. The problem is that you want to populate this state as a result of a route change.

The solution has 2 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:

export default function configureStore(initialState) {
    // the logic for configuring your store goes here
    let store = createStore(...);
}

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

All you have to do is to use the reduxStoreObserver.js provided in this Gist, now do this:

import observe from './reduxStoreObserver.js';

export default function configureStore(initialState) {
    // the logic for configuring your store goes here
    let store = createStore(...);

    observe(store,
        state => state.routing.locationBeforeTransitions.search,
        (store, previousValue, currentValue) => console.log('Some property changed from ', previousValue, 'to', currentValue)
    );
}

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment