React is A JavaScript library for building user interfaces. React is really a UI framework for writing pages, or it’s just a UI library, a library.

React is just a UI library, but the way it renders pages is something to learn from. JSX dynamically generates the DOM to render the page UI. He had no architecture, no templates, no design patterns, no routing, no data management, and he could do nothing but render the UI.

However, for a large and complex website, both design patterns and data management are indispensable. Therefore, it is impossible to develop large website applications only using React.

Here, for example, you can see the React component structure. The site renders the UI as a tree of components.

In React, data flows are one-way and always top-down. We can use props to pass data from parent to child components, but suppose we need to pass data from the Banner node at the bottom of the component tree to the Index node at the top.

React’s one-way data transfer principle does not allow us to pass data directly, but we can pass data up layer by layer through function callbacks, by calling functions of the parent component. The Banner calls a callback to pass data to Main, which passes data to Index via a callback.

In fact, it’s very common for a large website to share data like this, and if you pass it layer by layer through a callback function you’ll find that the entire code of the site becomes very disgusting. Basically, your code is an unmaintainable state. And the overhead of processing the data in this way is enormous. A careless is likely to fall into an infinite loop.

So when we get to a point where we need design patterns, maybe you already know MVC, MVVM, MV*. However, for React, we can also use an architecture mode that is more in line with React design idea, Redux.

Redux is a design pattern and project architecture solution that doesn’t rely on any library or framework. It can be used not only in React but also in Angular and Vue.

With the Redux architecture, the components basically don’t talk to each other, and the data is stored in a data warehouse called a Store.

By using Redux, we can strip out the state of the component and store all the data in the Redux data Store. If any component of the component needs to use the data, the component can go to the data warehouse to claim the data. If a component updates the data in the Store, the store pushes the latest data to all the components that subscribe to that data. That’s how Redux works.

Redux is a data warehouse that holds data together and handles the relationship between data and UI while isolating them.

The purpose of using Redux is to make state state changes manageable and predictable. While Redux seems simple in principle, it’s a bit trickier to figure out how he works.

This is mainly because the way it flows data is not particularly intuitive, it’s kind of like an event-driven approach, and we know that the hardest part of event-driven development is debugging. Redux uses a lot of obscure terminology such as Action, Reducer, Dispatch, etc. It’s hard to know what Redux should look like until you understand these terms. In addition, Redux’s documentation is not user-friendly and is full of new concepts such as pure functions, flux, Observable, and immutable, all of which are spoken without any concern about whether others can understand them or not.

In general, a Reducer Store will be created when Redux is used. There are several Reducer stores in this Store, and then we need to use the React component to render the UI. In addition, there are several Action directives corresponding to Reducer.

The Reducer in the Store is combined to form the data warehouse in the project. Redux called it State or data. The React component obtains data from the Subscribe Store, and then uses the data to render the UI. The UI is displayed to the user through the display. The user interacts with the component through the mouse and keyboard. The React component can only read data, but not write data. The UI component cannot directly access the Store to modify data.

Therefore, the UI must send Action instructions to the Store to make the Store modify itself, and the dispatch process of this instruction is called dispatch. After Action instruction arrives at store, it may be preprocessed by several middleware for data, and asynchronous data processing is also done here. After preprocessing, data will be delivered to reducer together with Action. Reducer will update the data state according to the instructions described in the Action. When the state is updated, the Store will push the data to the subscribed components. The components will re-render the UI according to the new data, and the users can see the changes. You can see that the Redux architecture is relatively complex in practice.

The above description is a bit complicated, but don’t panic. Let’s simplify the diagram, keeping only a few major parts, and learn about Redux by learning the simplified process.

After simplification, we only keep Reducer, Store, React component and Actions in the six layers. For clarity we have removed the Reducer from the Store, they are actually one and the same.

Store stores global data, and for the Redux project there is only one Store, which we can think of as a data warehouse with push functionality. We can use wechat moments to understand this concept. For example, if you add someone as a friend, their status will be immediately pushed to you as soon as that person posts it in moments. Adding friends is data subscription, sending friends circle is data push.

Reducer is a method to help Store deal with data. Reducer is a method, a process, a function, not a concrete object. Reducer can help Store initialize data, modify data, delete data. You may be wondering why we use Reducer to deal with data in such a cumbersome way instead of making changes directly in the Store, but the reason is very simple. For example, if you see a typo in your friend’s moments, you can’t change the status of that friend directly.

Any UI-level component has no permission to modify the data in the Store. According to the principle of one-way flow of data, they are read-only and cannot be written. You can only call them or send them a short notice and ask them to modify the data. Call him or send him a text message is an Action, and the process of calling him or sending him a text message is the dispatch Action. The reducer is the process he has to modify his circle of friends.

Finally, wechat will send you the message again after the modification, which is subscription and push.

Therefore, Store is the data warehouse with push function in Redux. Reducer is the data processing method of Store, which can help Store to initialize, modify or delete data. Actions are data update instructions. He tells the Reducer how to process the data so the Redux process is clear.

The data warehouse Store is created and the Reducer will initialize the data state at the same time. The React Component subscribes to the Store, the Store data is pushed in, and the UI is rendered.

If a component needs to change data it sends an Action, a process called dispatch. Actions are captured by the Store in an event-driven manner. The Store sends its current data and instructions to the Reducer, and the Reducer updates the data. After the Reducer update is complete, a new state will be output to the Store, which will push this new data to the React component that has subscribed to it. Then re-render the UI. This is a complete Redux workflow.

Redux is a design pattern and a project architecture solution. It does not rely on any library or framework, but people are used to Redux and React together. Here we introduce the use of Redux, to avoid confusion we do not use any framework.

First, you can install the Redux plugin in your project via NPM. As mentioned earlier, Store is the place where data is stored. There can only be one Store in the entire application.

import { createStore } from 'redux'
const store = createStore(fn);
Copy the code

Here, createStore needs to receive a function that is used to process action operations, which is what we said before. Therefore, it needs to receive action parameters, because it helps Store process data, it also needs to receive source data, and the return value is updated data.

const fn = (state = 0, action) = > {
    switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}
Copy the code

We can use getState to get data where we need to use it, and subscribe to listen for data changes, because Redux is a publish-subscribe mode, and only listeners can get it.

store.subscribe(() = > {
    const state = store.getState();
}))
Copy the code

When more data is needed, dispatch is used in conjunction with action to distribute it. We’ve agreed that an action needs to be an object that has a type property, so type is the type that you’re going to operate on, and if you’re going to pass parameters, we’re going to put parameters in the payload property.

const action = { 
    type: 'INCREMENT'.payload: 'parameters'}; store.dispatch(action);Copy the code

In this way, when we call store.dispatch, Redux will pass the action to the Reducer, which returns the new state through its own logical processing. Redux then records this new state and pushes messages to the subscribed components. That’s what triggers the function that’s passed in subscribe. The new state value can be obtained from the store.getState() function to complete the page update.

Let’s say we have a button and a div element on our page. This element displays a number, starting at 0, and increases the number displayed in the DIV when we click the Button.

<div id="count"></div>
<button id="button">button</button>
Copy the code

The js code is as follows, we first define reducer, in which we judge state+1 if type is INCREMENT, then createStore through createStore and pass reducer processing function.

Then subscribe to state and get the page div element when state changes and update the value of the content of div to state.

When the button is finally clicked, we distribute the action via Dispatch.

var reducer = (state = 0, action) = > {
    switch (action.type) {
    case 'INCREMENT':
      return state + 1
    default:
      return state
  }
}

var store = createStore(reducer);

store.subscribe(() = > {
    document.querySelector('#count').innerHTML = store.getState();
});

document.querySelector('#button').addEventListener('click'.function () {
    store.dispatch({type: 'INCREMENT'});
});
Copy the code

This is a basic process of using Redux, do you get it?

So when exactly do you need Redux?

  1. When components need to share data or state;

  2. When a component needs to be accessed anywhere at any time.

  3. When a component needs to change the state of another component.

  4. The site supports international language switching, login data sharing in case.

Redux is recommended for one or more of these situations, but if you’re still trying to decide whether to use Redux on your project, my advice is no. Technology is there to serve the business. In order to avoid top-heavy design, it is recommended to introduce new concepts only when needed, never for the sake of use.