3 Ways To Handle State Better in React

Use useReducer, custom hooks, and more

Caelin Sutch
Better Programming

--

Image of code on a screen.
Photo by Ferenc Almasi on Unsplash

React gives developers complete freedom over how state is managed within a component. React has two types of components: class components and functional components, which were introduced in React v16.

Class components use methods to manage state, such as this.state and this.setState for state, and componentDidMount() for running a side effect once a component has mounted. If interested, you can read more about these methods.

However, since most React developers now use React functional components, we’ll be focusing on functional components and their state, which is managed using React hooks.

In this article, we’ll be taking a look at some best practices that I’ve found for managing state within functional components — and truly taking advantage of the React hooks API.

Use useReducer for Complex State

Sometimes the useState hook won’t cut it, especially when dealing with complex state behavior that may involve large objects. The useReducer hook is a powerful provided React hook for dealing with complex state management that doesn’t require third-party dependencies. Also, it reduces the amount of data recreated with each render.

When combined with contexts and Typescript, useReducer can be incredibly powerful.

Let's take a look at how we might use this in real life:

See how much more modular and easier to read this is.

Custom Hooks FTW (i.e., for the win)

When using React hooks, you can sometimes end up with incredibly complex state logic within one component that utilizes multiple types of hooks to achieve one purpose.

Thankfully, we can make custom React hooks to encompass complex logic into a single accessible hook. This can come in handy for forms, toggles, asynchronous behavior, and anything else where you end up with a mess of hooks in your component.

We’ll take a look at an example of a custom hook to toggle items in a list of items. The code is as follows:

By abstracting all this logic out into a custom React hook, it’s not only easier to read, but also reusable across our application!

Global State Management

In most cases, you don’t need a state management library. Only in larger applications that are dealing with complex states should you bring in an external library to manage it.

Even then, reconsider if you can’t just use the provided Context API to share data between components.

If you decide you need an external state management tool, I highly recommend checking out Recoil, which is a super lightweight and easy tool for managing global state. Another popular library is Redux. There’s plenty of articles and discussions out there about how to use these tools effectively, so I won’t cover them in this guide.

Use Data Fetching Libraries

Pulling data from external APIs is a seemingly simple problem, but can get pretty complicated once you start needing to cache the data in memory (to reduce the number of API calls), update it, and access it in multiple places.

Thankfully, there are modern data fetching libraries like React Query for effectively fetching, caching, invalidating, and refreshing data from external sources. They can also be used for sending data to some external client and truly encompassing the whole workflow of interacting with a server.

Even better, some of these libraries like the Apollo Client encompass state management to handle the whole process of fetching data, caching it, and updating the UI automatically in a predictable, declarative, and readable way.

Conclusion

Managing React state can be complicated, but with these tips, I hope you can do it in a productive and readable way.

--

--