Thinking about using Redux and Redux saga to manage state

Time:2021-6-4

Original addressIn my blog, reprint please indicate the source, thank you!

summary

This paper introducesIUnderstanding and thinking of the idea, principle and architecture of Redux state management, as well as the practice of handling asynchronous operation with Redux saga

preface

You know, react is just a view layer of MV * architecture pattern. It is a kind of state machine. It is difficult to control large and complex applications only by using react. It needs some frameworks to help manage the state. Therefore, various architecture frameworks are interested in how to manage the state machine effectively, simply and easily. Facebook has long been aware of this problem and proposed the flux architecture, which is relatively complex; Later, Redux and mobx appeared. Mobx can deal with the scene of simple data stream and realize accurate update; Redux draws some ideas from flux and other frameworks. It is simpler and easier to understand than flux. It is used to deal with complex data streams and has strong scalability. Middleware such as Redux thunk, Redux promise and Redux saga were born in the community to handle asynchronous operations conveniently. Recently, Redux and its middleware Redux saga have been used in the project to manage state and handle asynchronous operations. This article will talk about my thinking and Practice on them.

text

Redux thought

Let’s talk about the background (needs)

I think it may be helpful to understand the idea of Redux and talk about the idea of MV * architecture mode.

The core of MV * architecture mode is the separation and decoupling of responsibilities. Different levels do different things. It can make a complex and Chaotic Application clear, and the code can be reused and easy to test. It is conducive to division of labor and cooperation to build larger and more complex applications.

What functions should an application include? Data flows between the three layers (MVVM mode realizes the synchronization of view and model through data bidirectional binding).

React renders according to state. It is just a state machine and does not solve the problem of managing state. When we simply use react to write components, we often encounter the problems of communication between components and management of component state; It’s OK for the latter to manage state simply. Once it’s complicated, it’s troublesome and error prone. If you encounter some operations that need asynchronous processing, you’ll feel numb.

When you encounter some anti-human operations in development, try to think about how to change your thinking to make it easier. Don’t be patient and comfort yourself that development is like this:)

Solution

Redux is used to solve the problems of state management, data flow, asynchronous processing, testing, team cooperation and so on

Redux is represented by a single object treeWhole applicationThe object tree representing the state is placed in a unique store   In, state is equivalent to a snapshot of the store; All components will get this state through API, and each component will get what it needs;

Redux defines the user’s operation or browser’s behavior (such as routing change) on the page as a state to updateactionThisactionIs a common object, which contains the category of the action to be executed and the data (if any) to be passed to the state,It only indicates the intention to change the state, which is equivalent to a signal. It can’t modify the state directly. Redux will process these signals centrallyThisactionIt’s up to you to decide when to launch;

To define a signal, you need to define different logic functions according to different signals(reducers) To update the state.

Let’s sort it out through this picture

Thinking about using Redux and Redux saga to manage state

Cough… For example, when a user clicks a button, the callback function you bind to the button calls one (or more)action creator,actionThe creator returns an update to the local data of the stateactionAccording to this (multiple)actionFind the corresponding reducers (the reducers need to be split) and follow theactionEach reducer is only responsible for updating the part that he cares about,The root reducer combines the outputs of multiple sub reducers into a single state treeTo generate a new state and save it in the store. The state in the store can be passed to the subcomponents through the corresponding API.

This is the whole data stream.

How does Redux handle asynchronous operations?

Redux uses the idea of middleware for reference and uses extensible middleware to transform the dispatch function. For example, Redux thunk makes the dispatch not only receiveactionYou can also take a function as an argument, in which you can perform asynchronous operations. For another example, Redux saga is more powerful and complex, which will be discussed later.

Redux architecture method

For react technology stack, Redux implements react Redux library to let Redux manage react applications (other frameworks also have corresponding libraries), which integrates some useful functions to automate some specific processes, such ascreateStoreIt is used to create a unique store, which can pass the root reducer into thecreateStoreThe middleware can be extended by making the store call the corresponding reducer automatically; provide<Provider store>Component and connect high-level component are used to wrap the render component and pass the state. Connect can also automatically dispatch so that you just callactionCreator can dispatch; Combine reducers are provided to combine segmented reducers.

Knowing these features, you can build large-scale applications with react router

The general idea is to use react router to divide the application into different pagesactionCreator also follows the page segmentation. There are components and containers under the corresponding page of each route, which store functional components and class components respectively. The former is used for rendering, while the latter is wrapped by connect as containers, and the containers are wrapped by components; Containers get the state from connect and map the required data to the props of the subcomponent, and then the subcomponent passes it down.

How to build react + Redux + react router, IAnother blogIt’s in the library.

With this architecture, it is easy to develop large-scale applications.

Problems in Redux

But when I went deep into the project development, I gradually found some problems

  • The project structure of this architecture is not flat enough, the file nesting is deep, the idea is complex, the construction and writing is troublesome, and it is difficult to start;
  • Because of allactionCreator is defined on the page level, so that sub component calls must be passed layer by layer, which is very troublesome, error prone and difficult to debug;
  • State is difficult to update locallyreselect
  • Redux is just a way of thinking. It defines a few simple APIs, which are very flexible. The architecture is not fixed, and the design method is not fixed (for example, how to design the state tree). But this is also its disadvantage. New people often do not know how to do it after reading it, and they are not friendly to new people

In short, Redux can be competent for the application of complex data flow, but it is also relatively difficult, and the early architecture is troublesome, which is suitable for experienced people.

Using Redux saga to handle asynchronous operations

Redux advocatesactionAnd reducer are as “pure” as possible without any “side effects”. However, some asynchronous operations, such as data acquisition, are necessary. Where can we deal with these side effects? Redux hands over these “impure” tasks to middleware, and through thecreateStoreThe middleware is applied in the system, and the process is handled by the storeactionYou can do some other operations on it before:

Thinking about using Redux and Redux saga to manage state

Redux saga is a powerful but uncomplicated middleware for asynchronous processing.

What is its thinking? Compared with other Redux asynchronous middleware such as Redux thunk and Redux promise, what is the difference?

Let’s look at the name first: saga, a term commonly used in cqrs architecture, stands forSeparation of inquiry and responsibility

Yes, it is the separation of dispatch and sagas. Saga providesactionListen function, just dispatch the corresponding type in the componentaction, you can automatically call the correspondingactionThe asynchronous processing function (sagas) is used to complete the task, which ensures that the task is only dispatched in the componentactionTo initiate asynchronous operations instead of calling Redux thunk or Redux promiseaction creators。

Another feature of Redux saga is that it can write asynchronous code synchronously, which is very intuitive and convenient. How can it be done? It uses the new magic generator iterator of ES6, which can perfectly solve the problem of asynchronous callback hell, allowing you to write asynchronously in a synchronous way. Saga is using the generator feature to make it very convenient and easy to understand. This is a common asynchronous operation of requesting background data

function *fetchNodeDetailByNodeId({ payload: { nodeId } }, { call, put }) {
      try {
        const { data, status }= yield call(fetchNodeDetailByNodeId, nodeId)
        if (data && status.errmsg === 'success') {
          yield put({
            type: 'setStates',
            payload: {
              nodeDetailData: data,
            },
          });
        } else {
          Message. Info ('I've made a mistake, please try again.. ';
        }
      } catch (error) {
        console.log(error);
      }
    },

Call and put are saga’s APIs, which are equivalent to dispatch. However, they do not really execute dispatch. They just send the instruction you specify to saga middleware to execute the instruction. In this way, the saga function is a collection of instructions, called effects, which are used for side effectsDescribe the task

Why describe instructions without calling them directly? This is because it is easy to test. If you call it directly, you have to simulate the function you call. See the Redux saga document for details.

I think Redux saga has the following advantages over other middleware:

  • The separation of inquiry and responsibility ensures the quality of serviceactionIn line with the design idea of redux
  • It is easy to understand and logic is clear
  • Make asynchronous operations easy to test by sending instructions instead of calling them directly
  • Monitoring and execution automation
  • It provides rich and powerful instructions to complete complex operations, such as non blocking calls, executing multiple tasks at the same time, etc

Logically, any Redux asynchronous operation can be completed by saga middleware, which is also competent for very complex operations, and is easy to understand (asynchronous operation is written in synchronous mode) and test. Combined with DVA, it can reduce the complexity of Redux and complete more powerful functions.

In this way, Redux can cooperate with saga to make them perform their respective duties, and the whole idea becomes clear

Redux advocatesactionTo be pure with reducer, let saga do all the impure tasks of asynchronous operation, and the reducer is still pure function; Define the correspondenceactionSagas of is specially used to handle asynchronous operations. I just need to dispatch where the component needsactionIt’s OK. It’s in line with the design idea of redux.

summary

Using Redux to manage application state is suitable for complex applications, and complex applications will have complex asynchronous processing. Do not use Redux for asynchronous processingactionCreator, which is not used to do this, also violates the design idea of redux. Redux gives these tasks to asynchronous middleware, which should be completed by them. Using Redux saga is a recommended choice. It understands Redux and what you need. In addition, since you use saga, you might as well try the DVA architecture. It’s worth a try.

Recommended Today

Hot! Front and rear learning routes of GitHub target 144K

Hello, Sifu’s little friend. I’m silent Wang Er. Last week, while appreciating teacher Ruan Yifeng’s science and technology weekly, I found a powerful learning route, which has been marked with 144K on GitHub. It’s very popular. It covers not only the front-end and back-end learning routes, but also the operation and maintenance learning routes. As […]