State Management & Data Fetching Libraries in React
Notes on using and not using state management and data fetching libraries in React.
State Management and Data Fetching are 2 of the most important things when building a React Application. Doing it right from the beginning is crucial.
Many people jump into using external libraries to solve these 2 big challenges from the beginning and later realize it’s hard to manage and maintain the project. This shouldn’t be the case.
External tools and libraries should be used carefully.
In today’s article, I want to share my experience and thoughts on using and not using external libraries for state management and data fetching.
🌟 Main Takeaways
Prefer using React’s built-in tools for managing state.
Don’t add unnecessary complexity. Keep things as simple as possible.
Opt-in for 3rd party state management libraries when the state management becomes hard to manage, update, maintain, and follow.
Use data fetching libraries.
State Management Libraries
State management libraries help manage and centralize state in React applications, which can grow complex as the application scales. However, as they might help, they can also add extra complexity which might not be necessary and beneficial.
When NOT to consider a State Management Library?
Small to medium-sized applications. React’s built-in hooks like useState, useReducer, and Context API are often sufficient for smaller applications where state management is simple.
Simple UI or state logic.
Short-term projects or prototypes.
When to consider a State Management Library?
Complex state logic across multiple components. When various components rely on and modify the same state, a central state management solution can simplify the flow and update of data.
Large applications. As the application grows and many people contribute, you might want to add a standard way of managing the state. Since you’ll be using one tool, everyone will describe their logic with it.
💡 My advice: Always start with React’s built-in tools for state management and evolve when necessary.
Don’t add unnecessary complexity. Keep things as simple as possible.
Keep in mind that there are no signals when you should start using a state management library or not.
Once you opt-in to using a state management library, the application’s structure and logic flow will change. So, think twice before taking this route.
For state management libraries, there are some popular options like Redux-Toolkit and Zustand. I’ve used Redux-Toolkit for e-commerce websites but mostly because it was already there, before joining the project. I’ve never used Zustand for real-life apps but I’ve read good things across the community.
⚠️ Remember: You can always combine both approaches. You can use React’s built-in tools for simpler pages and components and a state management library for the complex part of your applications.
For example, you can use the built-in tools for generic components like Forms and Inputs used across multiple pages where you use `useState` internally for managing their internal state. Then you can use the state management library for complex states across various pages.
Data Fetching Libraries
In React we don’t have a common way of fetching data. The React team doesn’t suggest how to do that in our React application. That’s why each team creates its implementation.
This sometimes might be good because we have a lot of freedom. At the same time, we have to manage common scenarios like loading states and error handling on our own. This includes a lot of boilerplate inside our components and applications.
It’s not very hard to make our implementation but when we do create it we will have to support and maintain it which might not be justified.
Thankfully, there are open-source libraries that solve exactly this problem. For example, TanStack's React-Query and Vercel’s SWR (for REST) or Apollo-Client and urql (for GraphQL).
These libraries make it easy to add data-fetching capabilities to our components through simple hooks. This way we follow the natural component lifecycle and mental model. They expose loading states and make error handling much easier inside our components. They only need a fetcher function that makes the call to the Server.
You can think of the data-fetching library as a thin layer around our API calls, adding additional functionality.
Another big reason for using data-fetching libraries is that they come with additional features like caching, automatic refetching, and background updates.
Example - without using a data-fetching library
Example - using a data-fetching library
In this example, we use React-Query.
As you can see from the examples, using a data-fetching library makes the overall component’s code and boilerplate much easier to read, follow, and maintain.
💡 My advice: Use Data Fetching Libraries.
📣 Articles worth reading:
How McDonald’s Food Delivery Platform Handles 20,000 Orders per Second from
by5 Writing Tips to Overcome the Blank Page from
byHow to prioritize effectively from
byManaging up: 3 things I wish I realized sooner from
by
I love it and fully agree. Glad to know I'm not the only one. I never took to Redux and it was one reason I focused on Angular at the time. When Hooks was finally officially released, I was able to use State and Context for state management, sans-redux. The project was a great success.
Useful information! I enjoyed reading it.
In React 19, new hooks were introduced to handle loading and error states.