react-redux with hooks is here!
In an alpha version.
The hottest thing in the React community right now is hooks. And it’s pretty sweet. It makes the code much compact and easy to read and work with.
If you use Redux with React you’re familiar with the connect()()
function. This is a higher-order component that injects props to the React components with actions and data from the store.
But now that we are in 2019 you can use hooks for this instead!
A quick translation of connect()() to hooks
The official docs on this topic are extensive and in-depth. It covers many edge cases. This is a TLDR; version of the docs. I’ll only show you the happy-path. I’ll take you step-by-step and refactor an old connect
to using the new hooks.
First an example with the old connect function
Ok so we have the connect
function that looks something like this
const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App)
The mapStateToProps
and mapDispatchToProps
function for a simple increase counter app looks like this:
const mapStateToProps = (state) => ({ counter: state.counter })
const mapDispatchToProps = {
increase: () => ({ type: "INCREASE_COUNTER" }),
}
I assume you already know how it works, if not, these posts might help.
An (almost) complete example of a React component using our connect function looks like this:
import React from "react"
import { connect } from "react-redux"
const increase = () => ({ type: "INCREASE_COUNTER" })
const App = ({ counter, increase }) => {
return (
<div>
The counter is {counter}
<button onClick={increase}>increase</button>
</div>
)
}
const mapStateToProps = (state) => ({ counter: state.counter })
const mapDispatchToProps = {
increase: () => ({ type: "INCREASE_COUNTER" }),
}
const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App)
The mapStateToProps
maps counter
from the Redux state to the prop counter
that is injected into the React component.
The mapDispatchToProps
maps an action creator to the prop increase
that is injected into the React component.
Provider
component.Now let’s translate this to hooks!
First you must install the latest alpha version of react-redux
. It’s the version 7.1.0
and later that contains hooks.
npm install react-redux --save
The code that uses hooks looks like this:
import React from "react"
import { useSelector, useDispatch } from "react-redux"
const increase = () => ({ type: "INCREASE_COUNTER" })
const App = (props) => {
const counter = useSelector((state) => state.counter)
const dispatch = useDispatch()
return (
<div>
the counter is {counter}
<button onClick={() => dispatch(increase())}>increase</button>
</div>
)
}
We use two hooks: useSelector
and useDispatch
. We use useSelector
to get the data out from the store and use it in the component, and we use useDispatch
to be able to dispatch action creators. You don’t have to use both useDispatch
and useSelector
, you can only use one of them if you want.
connect
, we must wrap the root component with Provider
for this to work.useSelector
In this example the useSelector
is very similar to the old mapStateToProps
- with one exception: it returns a value instead of an object. This is useful if your React component cares about one value from the store, like in this example.
In the old mapStateToProps
function we had to return an object even if we only wanted to use one value. We no longer have this limitation with hooks.
useSelector
can however still return object if you need to extract many values from the store:
const { counter } = useSelector((state) => ({ counter: state.counter }))
useDispatch
We no longer have access to something similar to mapDispatchToProps
. The way we now dispatch actions is with calling dispatch
and passing in an action. We get the dispatch
by calling useDispatch
hook.
const dispatch = useDispatch()
And we dispatch it by calling dispatch
passing in the return value from the action creator
<button onClick={() => dispatch(increase())}>increase</button>
More react-redux hooks
That’s it. I haven’t dig into the details, edge cases, and performance optimizations because the docs do that just perfectly: react-redux hooks docs. In the docs you can also learn about more hooks if you need more fine-grained control like useStore
.
Follow me on Twitter to get real-time updates with tips, insights, and things I build in the frontend ecosystem.