Subscribe to single property change in store in Redux
In Redux I can easily subscribe to store changes with
store.subscribe(() => my handler goes here)
But what if my store is full of different objects and in a particular place in my app I want to subscribe to changes made only in a specific object in the store?
There is no way to subscribe to part of the store when using subscribe
directly, but as the creator of Redux says himself - don't use subscribe
directly! For the data flow of a Redux app to really work, you will want one component that wraps your entire app. This component will subscribe to your store. The rest of your components will be children to this wrapper component and will only get the parts of the state that they need.
If you are using Redux with React then there is good news - the official react-redux package takes care of this for you! It provides that wrapper component, called a <Provider />
. You will then have at least one "smart component" that listens to state changes passed down by the Provider
from the store. You can specify which parts of the state it should listen to, and those pieces of the state will be passed down as props to that component (and then of course, it can pass those down to its own children). You can specify that by using the connect() function on your "smart" component and using the mapStateToProps
function as a first parameter. To recap:
Wrap root component with Provider
component that subscribes to store changes
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
Now any child of <App />
that is wrapped with connect()
will be a "smart" component. You can pass in mapStateToProps
to pick certain parts of the state and give it those as props.
const mapStateToProps = (state) => {
return {
somethingFromStore: state.somethingFromStore
}
}
class ChildOfApp extends Component {
render() {
return <div>{this.props.somethingFromStore}</div>
}
}
//wrap App in connect and pass in mapStateToProps
export default connect(mapStateToProps)(ChildOfApp)
Obviously <App />
can have many children and you can pick and choose which parts of the state the mapStateToProps
should listen to for each of its children. I'd suggest reading the docs on usage with React to get a better understanding of this flow.
Redux only offers a single generic way to know when the store has updated: the subscribe
method. Callbacks to subscribe
do not get any info on what might have changed, as the subscribe
API is deliberately low-level, and simply runs each callback with no arguments. All you know is that the store has updated in some way.
Because of that, someone has to write specific logic to compare old state vs new state, and see if anything has changed. You could handle this by using React-Redux, specifying a mapStateToProps
function for your component, implementing componentWillReceiveProps
in your component, and checking to see if specific props from the store have changed.
There are also a couple addon libraries that try to handle this case: https://github.com/ashaffer/redux-subscribe and https://github.com/jprichardson/redux-watch . Both basically let you specify a specific portion of the state to look at, using different approaches.