DEV Community

loading...
Cover image for React Hooks - useReducer

React Hooks - useReducer

techcheck profile image Andrew ・3 min read

What is it?

The useReducer hook is great to use if you need to handle more complex state.

If you're familiar with Redux, it's very similar to that, only you'd typically only use it for a component or two.

Complex state

Let's say you're fetching some data, and you want to display:

  • "loading..." while it's fetching
  • the data once you have it
  • or an error if there is one

You'll want all three of these to be in sync with each other. If you get the data, you want to make sure it's not loading and there's no error. If you get an error, it's not loading and there's no data.

This is a good use case for useReducer!

How to use it

We'll have to pass two things into the useReducer hook. A reducer, which we'll use to manage our state; and an initial state to start working off of.

Our initial state will be an object containing three keys: loading, data, and error.

Our reducer will listen for three different action types, and update the state accordingly. Those action types will be fetchDataStart, fetchDataSuccess, and fetchDataFail.

We'll put those in our file, but outside of the component:

//App.js
import React, { useReducer } from 'react';

const initialState = {
  loading: false,
  data: null,
  error: null
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'fetchDataStart':
      return {
        ...state,
        loading: true,
        data: null,
        error: null
      }
    case 'fetchDataSuccess':
      return {
        ...state,
        loading: false,
        data: action.data,
        error: null
      }
    case 'fetchDataFail':
      return {
        ...state,
        loading: false,
        data: null,
        error: 'whoops =/'
      }
    default: return state
   }
}

const App = () => {
  return (
    <h1>App Component</h1>
  )
}
Enter fullscreen mode Exit fullscreen mode

Notice we saved those under the constant variables: reducer and initialState. So we'll pass those into the useReducer hook.

const App = () => {
  useReducer(reducer, initialState);
  return (
    <h1>App Component</h1>
  )
}
Enter fullscreen mode Exit fullscreen mode

The useReducer hook will return two things in an array: the state, and an action dispatcher to update the state.

We'll grab those with array destructuring, similar to state and setState with the useState hook.

const App = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <h1>App Component</h1>
  )
}
Enter fullscreen mode Exit fullscreen mode

Dispatching actions

Our useReducer hook is all setup. Now, let's use it!

We'll create a function for fetching data, and we'll dispatch different actions based on the state of that fetch request.

(Those actions are being checked for in our reducer via the switch statement and our case clauses.)

const App = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  const fetchData = () => {
     dispatch({type: 'fetchDataStart'})
     fetch('ourbackend.com/data')
     .then(res => {
        dispatch({
          type: 'fetchDataSuccess',
          data: res.data
        })
     })
     .catch(error => {
        dispatch({type: 'fetchDataFail'})
     })
   }
   return (
      <h1>App Component</h1>
   )
}
Enter fullscreen mode Exit fullscreen mode

Accessing the state

Accessing the state is very easy. useReducer returned that in the array we destructured. We saved it to the constant variable, state.

That state (our initial state and the updated state) is an object. So we'll access the values right in our component like so:

  return (
     <h1>App Component</h1>
     <p>{state.loading}</p>
     <p>{state.data}</p>
     <p>{state.error}</p>
  )
Enter fullscreen mode Exit fullscreen mode

Conclusion

The useReducer hook is extremely helpful when different states depend on each other.

As for bringing in Redux, I'll typically do that if there's complex state for the entire application. If it's only for a component or two, I'll use useReducer.

I have a YouTube video where I go into more detail. I explain the reducer function in greater depth there as well.

If you like learning about similar topics, feel free to check out my YouTube and Instagram.

Hope this helped somebody and thanks for reading!

-Andrew

Discussion (23)

Collapse
thatanjan profile image
Anjan Shomodder

useReducer is a very useful hook. But it will be too much if it is used in simple cases.
I have a experience of that. So, it should be used carefully.

Collapse
techcheck profile image
Andrew Author

I could see that. Good call

Collapse
jotsarupsingh profile image
jotsarup-singh

i call it mini version of redux.

Collapse
techcheck profile image
Andrew Author

That's how I think of it 😂

Collapse
reactifystudio profile image
Reactify

So can I ditch redux and use this stuff alone?

Collapse
techcheck profile image
Andrew Author • Edited

Good question. Redux is great for combining multiple reducers. (and combining all the dispatched actions to work together). It's also good for injecting middleware for developer tools and performing asynchronous tasks (fetch data, etc..) inside actions. I might have to add an edit to the blog 🤔👍.

Thread Thread
reactifystudio profile image
Reactify

What others do I need I hear of thunk redux and such.but I don't know much about it. I've used context API alone

Thread Thread
reactifystudio profile image
Reactify

I see other stuff like redux thunk. Can you advise me on everything I need for redux. I'll have 100 code days in Frontend (react and Firebase)
.

Collapse
jotsarupsingh profile image
jotsarup-singh

@reactifystudio it can be used in small medium size projects but for large application its difficult to manage.

Thread Thread
reactifystudio profile image
Reactify

Okay thanks. And which other tools you use in React?.

Collapse
petrtcoi profile image
Peter Tcoi

Is there any naming convention for components with useDispatch from react-redux?

const dispatch = useDispatch()
and
const [state, dispatch] = useReducer(reducer, initialState)

Collapse
ical10 profile image
mhusnirizal

Thanks! Clear and concise, just what I needed.

Collapse
techcheck profile image
Andrew Author

Thanks! 🙏

Collapse
alpinstang profile image
John McDonald

Great article! Hooks are the best thing since functional components in React!

Collapse
techcheck profile image
Andrew Author

Thanks! Agreed!

Collapse
kleguizamon profile image
Kevin Leguizamon

Hey man, greats tutorial 👍

Collapse
techcheck profile image
Andrew Author

Thanks! 🙏

Collapse
thematrixadmin profile image
Oskar Pietrucha

Nice tutorial, thanks! I'm gonna implement it in my projects

Collapse
techcheck profile image
Andrew Author

My pleasure! Awesome to hear!

Collapse
vanaroth_aya profile image
Vanaroth

Very good post, thank you.

Collapse
techcheck profile image
Andrew Author

Thank you 🙏

Collapse
spyda247 profile image
Babajide Ibiayo

Awesome!!! Thanks. I enjoyed the video so much that I coded each line and then went ahead to build an express API server to fetch random quotes off a mongoDb database running on my laptop.

Collapse
techcheck profile image
Andrew Author

That's so awesome to hear!

Forem Open with the Forem app