Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Why do I stop using Redux?


May 31, 2021 Article blog


Table of contents


Redux is a revolutionary technology in the React ecosystem. I t allows us to store immutable data globally and solves the problem of prop-drilling in the component tree. When immutable data needs to be shared between applications, it is still a great tool for easy scaling.

But why do we need a global store? Are our front-end applications really that complex, or are we trying to do too much with Redux?

The problem with the single-page application

The advent of single-page applications (SPA) such as React has brought many changes to the way we develop web applications. I t separates our back end from the front-end code, allowing us to focus on consistency and separation of concerns. It also introduces a lot of complexity around the state.

Now, getting data asynchronously means that the data must be in two places: the front end and the back end. W e must consider how best to store this data globally so that they are available to all of our components while maintaining the data cache to reduce network latency. Now, a large part of the burden of front-end development comes from the maintenance of our global storage, and we want to make sure that those storages are not plagued by state errors, data denormalization, and stale data.

Redux is not a cache

One of the big problems most people encounter when using Redux and similar state management libraries is that we think of it as a cache of back-end states. We get the data, add it to storage through reducer/action, and periodically reacquir it to make sure it's up-to-date.

We do so much with Redux that we even see it as a comprehensive solution to the problem.

The point is that our front-end and back-end states never really sync, and we can create the illusion that they are in sync at best. T his is one of the disadvantages of the client-server model and why we need to cache. However, synchronizing caches and maintaining state is complex, so we shouldn't recreate this back-end state from scratch, as Redux encourages.

When we started recreating the database at the front end, the lines of responsibility between the back end and the front end quickly became blurred. As front-end developers, we don't need to fully understand tables and their relationships to create simple UIs.

We also don't have to know how to standardize our data at a high level. T his responsibility should rest with those who design the table (back-end developers). Back-end developers can then provide abstractions for front-end developers in the form of documented APIs.

Now, countless libraries (redux-observable, redux-saga, redux-thaga, redux-thunk, etc.) are being built around Redux to help us manage back-end data, each adding another layer of complexity to an already cumbersome library. I believe most of them have not achieved their goals. S ometimes in order to move forward. We need to take a step back.

What if we no longer manage back-end state in front-end code and just think of it as a cache that needs to be updated regularly? W hen we think of the front end as a simple display layer to read content from the cache, our code becomes easier to use and more suitable for pure front-end developers. We've gained all the benefits of separating concerns while avoiding most of the disadvantages of building a SPA.

An easier way to get back-end state

I think it's much better to have two libraries than to use Redux (or similar state management libraries) to store back-end states.

React Query

I've been using React Query for months in most of my personal and work projects. This library has a very simple API and several hooks for managing queries (getting data) and mutations (changing data).

Since using React Query, I've not only improved efficiency, but I've ended up writing 90% less sample code than Redux. I found it easier to focus on the UI/UX of the front-end application and stop worrying about the entire back-end state.

To compare this library with Redux, let's look at a code example of both approaches. I implemented a simple TODO list from the server using regular JS, React Hooks, and axios.

The first is the Redux implementation:

import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import axios from 'axios';
const SET_TODOS = "SET_TODOS";


export const rootReducer = (state = { todos: [] }, action) => {
  switch (action.type) {
    case SET_TODOS:
      return { ...state, todos: action.payload };
    default:
      return state;
  }
};


export const App = () => {
  const todos = useSelector((state) => state.todos);
  const dispatch = useDispatch();
  useEffect(() => {
    const fetchPosts = async () => {
      const { data } = await axios.get("/api/todos");
      dispatch({
        type: SET_TODOS,
        payload: data}
      );
    };
    fetchPosts();
  }, []);
  return (
    <ul>{
        todos.length > 0 && todos.map((todo) =>{
            <li>{todo.text}</li>
        } 
      )
    }
    </ul> 
  );
};

Note that you haven't even started processing reacquiring, caching, and invalidating here, just loading the data and storing it in global storage at load time.

The same example of react Query implementation:

import React from "react";
import { useQuery } from "react-query";
import axios from "axios";
const fetchTodos = () => {
  const { data } = axios.get("/api/todos");
  return data;
};
const App = () => {
  const { data } = useQuery("todos", fetchTodos);
  return data ? (
    <ul>{data.length > 0 && data.map((todo) => <li>{todo.text}</li>)}</ul> 
  ) : null;
};

By default, the examples above include data reacquiring, caching, and invalidation of outdated content with reasonable default values. You can set the cache configuration at the global level, and then you can forget about it -- generally enough to do what you expect

Now, whatever data you need, you can use Query hook with the unique key you set (in this case, "todos") and use asynchronous calls to get the data.

When you want to change the interface state, React Query provides a useMutation hook.

Once you start using this library, you'll find that Redux is too bulky in most projects. A fter processing the data acquisition/cache portion of the application, the front end has almost no global state to handle. You can use Context or useContext-useReducer to work with the remaining small amount of content instead of Redux.

Or, better yet, use React's built-in state as your simple front-end state, which is fine.

// clean, beautiful, and simple
const [state, setState] = useState();

Instead of getting stuck in this ambiguous middle state, we should separate the back end from the front end more thoroughly. T he libraries mentioned in this article represent a change in the way we manage state in a single-page application and are a big step in the right direction. I look forward to seeing how they affect the React community.

Source: dev.to/g_abud/why-i-quit-redux-1knl

Above is W3Cschool编程狮 about why I stopped using Redux? Related to the introduction, I hope to help you.