Using redux with react hooks

May 23, 2019

A post by Will Mayger
Twitter . Instagram

You are probably already a fan of redux and react if you are reading this. And are probably looking to start using redux with react hooks.

Before I get to that, I want to touch on a few things first…

Firstly, for anyone new to redux you may be looking into this to try to understand why people might want to use redux.

(If you already know what Redux and React hooks are, you can skip this first bit)

What is Redux?

Without boring you, and put very simply, redux is a state management tool. It will enable you to control all of your state in one place, in a nice clean way.

This can help make your react (or other) applications cleaner, more maintainable and simpler, without the need of passing loads of state variables down the react tree.

On a more opinionated point of view, I have never been a huge fan, because it will add time to your build and is often overused, however it definitely has its place and it is a pretty important part of the ecosystem to learn, so don’t get lazy!

Not to mention, many projects and companies use redux and it is well supported, so it is almost essential if you like any framework/Library like React or Vue.

What are React hooks?

React hooks are the new way, in react, to use state and lifecycle features. They have been around for around for a few months (at the time of writing).

They make it easier and cleaner to write react and provide a way to avoid using classes and many lifecycle methods.

Basically, they make your life as a react developer better.

If you want a more in-depth view about react hooks checkout some of my other posts such as React hooks vs Classes or Using window.addEventListener with react hooks.

To redux, or not to redux?

As I mentioned previously I believe that redux is often overused in many projects that may not necessarily need it which can increase development time.

Many times people only use it for the state management side of redux, which is the main aspect, but redux also ships with a lot of code to fix a lot of problems, such as the ability to make use of middleware.

With this being said it is overused because it is a very useful tool that will make certain parts of developing most applications a lot easier.

For example, what would you do if you needed a function/action, that controlled a state property, in 10 different components at different levels in your react dom tree?

Use a global function? Pass it through props all over your application? Use React’s Context API? …or use Redux?

In most situations you should avoid using global functions. And in most situations you should avoid passing a function/action through many components that aren’t using it.

That leaves two options, React Context API or Redux?

In this post we will be going over Redux, but in the future I will do a similar version using React’s Context API.

Just remember, don’t use redux if you do not actually need it because you will be adding complexity to your codebase.

Redux and react hooks

Many people were wondering if you still need redux, and in my opinion, it still has its place, and whilst you can do most of the same thing using React hooks + React Context API, you still need to set that up, and then what about all the helper functions or middleware that come along with react-redux?

Well, with using redux with react hooks is actually making the redux api and implementation cleaner, and fit into the React ecosystem better.

No longer will you need to use connect(), you will now be able to use useSelector to do the bulk of your work now, which as you have probably guessed, is a hook.

Before going any further, react-redux react hooks implementation is still in alpha stages, but I would highly recommend giving it a go.

Let’s look at the main parts of the new API briefly.

useSelector

useSelector() This is how you access a store/state property. Simply give it a variable that you want the state value to be called, pass in a function that takes the state and returns the state property value that you want.

Let’s say this is your store looks like this: { count: 0; }, and you want to get the int value of count in your component, it would probably look something like this:

const count = useSelector(state => state.count);

Here is a snippet from the official documentation:

const result : any = useSelector(selector : Function, equalityFn? : Function)

useDispatch

useDispatch() This is just a hook that you need to call to be given your dispatch function.

You would use it a bit like this, to get your dispatch function:

const dispatch = useDispatch();
dispatch({ type: 'increment' });

Tutorial/Basic setup for react hooks with redux

Firstly initiate a new create-react-app by typing: npx create-react-app react-hooks-with-redux-example

Once created, navigate into the project by typing cd react-hooks-with-redux-example in your terminal, and install the following packages using yarn:

yarn add redux yarn add react-redux@7.1.0-alpha.5

Now let’s start coding our redux and react hooks project, I am not going to be worrying too much about architecture here to keep this purley about redux with react hooks and to keep it nice and simple!

src > index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import reducers from './reducers';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';



const store = createStore(
  combineReducers(reducers),
);

ReactDOM.render(
  (
    <Provider store={store}>
      <App />
    </Provider>
  ),
  document.getElementById('root')
);

serviceWorker.unregister();

In this file we are importing our redux based imports:

import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import reducers from './reducers';

And then we create a store/state using our combined reducers (we will create some reducers in a second), and then apply it to our react dom tree like so:

const store = createStore(
  combineReducers(reducers),
);

ReactDOM.render(
  (
    <Provider store={store}>
      <App />
    </Provider>
  ),
  document.getElementById('root')
);

Let’s create our reducers now: src > reducers.js

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

const toggle = (state = false, action) => {
  switch (action.type) {
    case 'TOGGLE':
      return !state;
    default:
      return state;
  }
}

export default {
  counter,
  toggle,
};

Here we create two standard reducers, and export them in an object.

A reducer is just a way of determining what bit of our store needs updating when you use an action to change the state. This is the same in the standard way of using redux.

To keep things simple we won’t bother creating an action file, instead we will just directly code the actions into our dispatch functions, feel free to do this however you wish.

Finally our implementation/use of redux with react hooks:

src > App.js

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';

function App() {
  const dispatch = useDispatch();
  const counter = useSelector(state => state.counter);
  const toggle = useSelector(state => state.toggle);

  return (
    <div
      style={{
        background: toggle ? '#ece1c2' : '#fff',
        height: '50vh',
        padding: 50,
      }}
    >
      <h1>Counter: {counter}</h1>
      <button
        onClick={() => dispatch({ type: 'INCREMENT' })}
      >
        add
      </button>
      <button
        onClick={() => dispatch({ type: 'DECREMENT' })}
      >
        minus
      </button>

      <button
        onClick={() => dispatch({ type: 'TOGGLE' })}
      >
        Toggle Colour
      </button>
    </div>
  );
}

export default App;

Here in this file, we are just using all of the parts we have just set up. This is where the new redux - react hook api comes into play. As you can see we do not need to use connect() to get our state and dispatch functions which makes using redux instantly a lot cleaner, in my opinion.

On each button click we are dispatching various actions.

This roughly looks like this: click > dispatch action > check action in reducer > update store/state > re-render component

The add and minus buttons make use of the counter reducer, and actions trigger either an increment or decrement, and the toggle is being used to toggle the background colour of our container.

Conclusion

I think, if you like react, and react hooks, this is something vital that you will need to learn and understand when the first version gets released.

Redux is already insanely popular, and with react hooks being a hit in the react community it makes sense to get used to using them both.

The upcoming API for redux combined with hooks seems like it is going to be a dream to use and make projects cleaner with less setup involved.

I hope this post has helped!

Here are a few links related to this topic that you may find interesting:

https://redux.js.org/basics/reducers

https://react-redux.js.org/next/api/hooks

https://reactjs.org/docs/hooks-reference.html