Provide Redux Actions and Reducers to React Components Automatically
Update: This post is somewhat outdated, though many of the concepts remain the same. See https://medium.com/@timbur/bridging-the-gap-between-redux-and-the-declarative-nature-of-relay-graphql-tutorial-45a0bf5bd13a.
In my previous article I gave a detailed description of the ins and outs of building an application using react-redux-provide among a handful of other libraries. That article was mostly written for folks who may not be entirely familiar with Redux or even React. But for those already familiar, this article is for you. :)
At first glance, it might seem like there’s a lot of magic going on under the hood, but there isn’t! The providers paradigm revolves around just two concepts.
What is a provider?
A provider is nothing more than a combination of actions and reducers designed to work together to manage shared state across multiple components. A merge function, middleware, and/or enhancer may also be included.
Each provider should typically only do one thing and do it well, such that it is completely decoupled from components and thus more easily reusable and distributable. This in turn allows components to also be more easily reusable and distributable.
How do providers work with components?
If you’ve used react-redux to bridge the gap between React and your Redux actions and reducers, you’ve almost certainly noticed a pattern with the way you use its connect function to mapStateToProps and mapDispatchToProps. The react-redux-provide package is designed to eliminate this boilerplate. There’s nothing magical going on under the hood. It uses a simple loop that compares the component’s propTypes to the keys of each provider’s actions and reducers.
By default, the actions are mapped such that when a component calls this.props.someAction(), it’s essentially calling provider.store.dispatch(provider.actions.someAction()). And reducers are mapped such that components will always have the current state of the provider’s relevant reducers. You can customize the way these are mapped, but I have personally never found it to be necessary.
Decorating (i.e., wrapping) components with the provide function will allow them to use providers obtained via React’s context. Passing providers as a prop to any decorated component will instantiate a new contextual Redux store for each provider. You can also pass a combinedProviders prop (which will cause certain providers to use the same store) and/or a providedState prop.
And since I’ve been asked about it more than once, a provider’s store is the same as a Redux store. It is created based on the provider’s actions, reducers, middleware(s), and/or enhancer(s). Multiple stores are good because it lends to an even further separation of concerns while also enabling efficient re-rendering. It also makes it easy to use multiple contexts at the same time.
Suppose you have one component that displays some count, and another that controls the count. See the comments within the following code for how to achieve this using a provider:
It doesn’t get much simpler than that!
I’m on the road right now so I’ll have to stop here, but that should be enough for anyone already familiar with React and Redux to get started. If you have any questions or comments, it’s probably easiest to message me on twitter @_timbur or create an issue on GitHub.
Remember to check out my previous writeup for a more detailed version of this post, if you haven’t already!