1. Contestants enter

React state management is a topic that many people don’t want to mention.

Redux: Player # 1, the most popular player, must be used with React-Redux. I don’t care about asynchrony, so I often hear what redux-thunk, redux-saga is its subordinate, specialized in wiping the ass. Characteristic is difficult to use, if according to the official document written method to use, basically want to die. Recommended reading: www.zhihu.com/question/33…

Mobx: Contestant # 2, using a wiretap runs counter to React’s ideology.

Dva: Redux encapsulation, written as Redux-Saga, generator.

Rematch: Redux encapsulation, similar to DVA, is divided into reducers and effects in model, which is not concise enough.

AD: So 🐤 Retalk is the simplest Redux package ever, and don’t miss it if you walk by: github.com/nanxiaobei/…

2. React Hooks

In any case, Hooks are here, and the old state management was for the old development style, just add a few useBlabla() to get some closure for Hooks.

They are ponderous, old, perfunctory compared with the lightness of Hooks.

Is there state management specifically for Hooks? So far there is no popular return, basic are old players to do a part-time job, a bit of neither fish nor fowl.

Not revolutionary enough.

3. Why do we need state management?

One is to solve communication problems between adjacent components.

Although this can be solved by “state promotion”, there are two problems:

  1. Every time a child component is updated, it triggers an overall update of the parent component that is responsible for issuing the state (this also happens with Context), and then writes a bunch of pureComponents and shouldComponentUpdate. React design dregs are written enough, too sad.

  2. If more logic is written in the parent component, can the code still be read? No consideration for the feelings of the parent component.

So “state promotion” is not a good idea, and state management is still needed.

In addition, one of the most important benefits of state management is

It takes the logic of “interacting with the server” and “manipulating the data” out of the component, which simply receives the processed data. This is equivalent to the separation of the Service layer, a good development model.

The biggest benefit is that the code and logic are separated and the components do what the components are supposed to do.

So we need state management.

4. What kind of state management do we need?

If you start with Redux, you’ll find that it provides a global store. And then what? Then it did not say anything, there is any problem on their own to solve it, I sleep first.

The most common scenario encountered in real business development is the need to distinguish between different “modules”, which is the most basic requirement.

Vuex is pragmatic and provides the concept of modules.

Redux? Of course, you have to rely on yourself, we provide a concept on the line, so simple things, you go to do it.

Failure to regulate API design is bound to result in countless different implementations. (single bet x 2)

CHAOS.

What kind of state management do we need?

We need state management that conforms to the national conditions in the primary stage of socialism with Chinese characteristics.

We need to be able to divide different modules, modules are independent, and modules can communicate freely with each other.

Many state management libraries only consider module “independence”, but remain inhospitable silent on “communication”.

Independent and connected — that’s what modules are all about.

5. How are modules divided?

In general, it is recommended to separate modules based on the basic route entry, which is the idea in DVA (its folder is simply called routes).

This is also consistent with the natural way of thinking, dividing the routes, that is, the natural way of thinking that they belong to different modules.

And each state management module, which we call “model”, is proposed to be bound to the routing entry component, each entry component and its sub-components, as a whole corresponding to a Model.

---A
    index.jsx
    model.js
---B
    index.jsx
    model.js
---C
    index.jsx
    model.js
Copy the code

6. How does the module communicate?

Modules are independent, of course, modules modules, are they not independent modules?

How do modules communicate?

Within the component, you can get your own model and other models, which is not difficult.

Mainly, in the model, each of its methods need to call each other, and at the same time need to get the data and methods of other models, which is the meaning of communication.

It has to be simple enough.

This is a good and thorough design.

7. How to obtain the model from the Hooks component?

Most directly, we want to access a model in the component via Hooks.

const { someStateInA, someActionInA } = useModel(a);
// or
const { someStateInA, someActionInA, someStateInB, someActionInB } = useModels(a, b);
Copy the code

UseModel () passes in a model, so that if you want any model, you have to import the model file in the component, which is not free enough to rely on having to import the file.

As long as it’s difficult to operate and write more code, it’s not good design.

In addition, Hooks are used to make code clearer, we can’t go against the overall system design philosophy like Mobx.

Therefore, it is better to separate model acquisition. UseModels (a, B) introduces multiple models at one time, which is not clear enough.

Can’t rely on files to introduce clarity, so:

const { someStateInA, someActionInA } = useModel('a');
const { someStateInB, someActionInB } = useModel('b');
Copy the code

Relying on a string eliminates the need to import files in each component. UseModel () can access only one model, and the code is clear enough.

This is the design we need.

8. How to design the model structure?

Generally speaking, a model can be divided into two chunks: data (State) and methods to operate data (reducers and Effects).

Reducers and effects, or mutations and actions in Vuex, are designed to distinguish between direct changes and asynchronous operations, synchronous functions and asynchronous functions. It’s not neat enough. Can you merge it into one?

The answer is yes, we call it actions.

The update state method is injected directly into the Model, so an action can be either synchronous or asynchronous and is simply called as a function.

Therefore, the model can be divided into two parts:

exports default {
    state: {},
    actions: {},}Copy the code

9. How to design model communication?

The model communication is mainly to implement access to other needed things in the action.

Free and unrestricted communication.

An action needs to access the following: 1. Its state, 2. Other modules state, 4. Other modules Action, 5. Own state updater.

To simplify, you need to access: 1. Own model, 2. Other Models, 3. Own state updater.

1. Model; 2. Own state updater.

So you really only need two methods: getModel() and setState().

GetModel () gets itself, getModel(‘other’) gets the others.

How do you get these two methods?

  1. Access this. Hooks: Do not violate the system’s design philosophy.

  2. In Vuex, context is injected as the first parameter of a function, which is counterintuitive.

  3. The import method in the model file is too troublesome, as long as the operation is troublesome and the code is written more, it is not good design.

So the only way to do that, as you can see in the design of Rematch, is to inject methods into the parameters.

Turn actions into a function:

exports default {
    state: {},
    actions: ({ getModel, setState }) = > ({
        someAction() {
            const{ someState, someOtherAction } = getModel(); }}}),Copy the code

There is an aesthetic issue here. GetModel () is used for many actions, but in practice it is written down to model() because of the l height problem and ugly.

Model () gets itself, model(‘other’) gets the others.

10. What does flooks mean?

Thus, Flooks, Flukes, is born:


🍸 flooks – github.com/nanxiaobei/…


import { setModel, useModel } from 'flooks';

const a = {
    state: {},
    actions: ({ model, setState }) = > ({
        someAction() {
            const{ someState, someOtherAction } = model(); . setState(payload); } }), } setModel('a', a);

function A() {
    cosnt { someState, someAction } = useModel('a');
    return(...). }Copy the code

Natural modular support.

There are only two apis, setModel() and useModel().

Add the two parameters of actions, Model () and setState(), and that’s it.

Simple enough to do everything.

One more thing

Decentralization, decentralization, decentralization.

It’s all about simpler development.

No need for top-level distribution of stores, no need for store folders or store.js files.

No top-level createStore(), no top-level Provider.

When registering a Model, you don’t need to first import the model in a centralized file. You can do everything in your own folder.

Connect the component to the Model directly with setModel(), and that’s it.

Modularity, building blocks like combination, simplicity, flexibility, this is our concept.

Each component and model forms a self-organization, while they have access to all parts of the world. They can meet anywhere in the world without reporting to the authorities.

This is our philosophy: independence, freedom, individuality, the world.