Use React hooks to connect your Redux store and your components
Say goodbye to HOCs or connectors and welcome the React hooks era
- Can React hooks and Redux coexist?
- TL;DR: Focus on the integration between your app state and the components
- Connecting components using hooks
Can Rect hooks and Redux coexist?
I will say it, React hooks and Redux can and should coexist. Especially when you already have Redux holding your application state, there is no reason to drop it off and start from scratch just because you can write a reducer using hooks. Let redux do what it does best and instead, focus on the integration between your app state and the components.
Redux is great by managing state! You got middlewares such as redux-thunk, a damn good debugging tool for chrome, composition of reducers and thousands of articles about it around the web.
TL;DR: Focus on the integration between your app state and the components
One desired output for our React apps is to have our components as dumb as possible. This means to have less logic done inside the component as possible, in a way that it only depends on its props in order to result in different outputs.
Dumb components are almost a representation of the DOM. It’s very reusable and very easy to understand what is going on.
Now, imagine that your component needs to compute some data from the app state before rendering. Without hooks you have basically two options:
- Connector: An option would be to just write this logic inside your component. In this situation, you will need a connector to inject the state data into your component and to write the logic inside the component before rendering it. Such as calling fetchData() inside your componentDidMount and controlling loading and errored states.
- HOC: Another option is to have a High-order-component which do the hard job for your component and inject the cooked data as props into the dumb component.
Both of these options works well and they got the job done so far. The problem is that in both cases you end up with a huge mix of Component code (e.g jsx) and core logic code which is harder to maintain as the complexity of your application grows and it is also less reusable. I won't go into more detail about that. If you're convinced enough that React hooks can bring fresh air in this process follow along to the next section. If you're not, just keep reading it anyway.
Connecting components using hooks
In order to illustrate how you can connect your component using React hooks, we will create a simple todo list which fetches the data dynamically and also a detail view for a single todo. I will use the library react-redux which offers us a set of very handful hooks.
There are basically 2 hooks from this library we are going to use and another one which is a customization of one of them.
- useSelector: this hook allows you to extract data from the state by passing a selector into it. You can also define which equality check if you want to change how it is defined whether the selector result has changed or not.
- useDispatch: this hook will simply return the dispatch function from the store. Allowing you to dispatch actions from pretty much anywhere.
The custom hook useAction:
This hook receives an action, binds it to the dispatch function and returns the boundAction. Pretty easy, right?
With that, we can finally start building our real hook useTodo:
- Receives the id of the todo in question
- Create state variables to handle loading and error states
- Hook his action fetchTodo by using the previously create hook useAction
- Create a memoized selector to grab a todo by id from the store
- Grabs the todo from the store by passing the recently created selector into the useSelector hook
- Defines a useEffect hook which will fetch the todo whenever it isn't found in the store
- Finally, it returns the todo and the loading and error states.
Let's see how easy is to have our component connected using this hook we just created:
If you want to go further and completely isolate the logic from the presentational component, you could split the component above into 2 components, a wrapper, and a dump component:
I have gone through the connectors and HOCs path in the past and I am loving the fresh air Reacr hooks brought. This "data hooks" (as I like to call) allows me to have all my data managing policy encapsulated into a reusable piece of code that can be shared and consumed in many ways across different components. I can write much simpler components and ensure that they are using the best data fetching policy available in the codebase. Thus avoiding unnecessary re-fetchings and re-renders. If you want to master this subject I strongly recommend you to go through the react-redux docs for hooks and also read more about memoized selectors.
The full source code used for this article can be found here:
Thanks for your time, I hope you enjoyed this reading.