Refer to the following documentation for this article

Redux official documentation

Redux Chinese document

Portal πŸ€–

  • React Brochure – Get Started JSX βœ… βœ…

  • React Brochure – Set sail βœ… βœ…

  • React Small volume – Hooks βœ… βœ…

  • React Brochure – CSS solution

  • React Brochure – Life Cycle βœ… βœ…

  • React Brochure – State Management Redux βœ… βœ…

  • React Volume – State Management Redux middleware

  • React Volume – State Management Mobx

  • React brochure – Router

  • React Volume – Performance optimization

  • React Booklet – SSR

  • React Brochure – React Ecology βœ… βœ…

Story synopsis

Redux evolved from Flux as a set of third-party tools for managing public state

For Flux thoughts, please refer to Ruan Yifeng’s network log

Although not officially developed for React, it has become the de facto standard for managing React state

Redux workflow

  • Dispatch action (Dispatch (action))

  • The Reducer receives the action, distributes and processes it and returns a new state to the Store

  • The Store received new state data that changed

  • The View View layer updates the page with the store.subscribe subscription store

The specific process can be seen in the following figure


The three principles

Single data source

Although Redux is derived from the Flux architecture, it is not designed entirely in accordance with the Flux architecture

For example, the Flux architecture allows multiple stores but only one store is allowed in Redux

All states are stored in a single store

This ensures that the data is traceable and predictable

Immutable data

Don’t try to modify the store data directly because this will cause your app to have unpredictable results

The only way to change state is to trigger an action

This will return a new store every time you make a change

Redux can record every store change for debugging and so on

Using pure functions

This function needs to produce the same output at the same input value. The output of a function is independent of any hidden information or state other than the input value, or of the external output generated by the I/O device. This function cannot have semantically observable function side effects, such as “firing events,” making output devices output, or changing the contents of objects other than output values. —— Wikipedia

The Reducer is just some pure functions this means that the results of the Reducer will be controlled only by actions

Back to the official definition of Redux

Predictable State Container for JS Apps —– Redux official

Predictable is the least of the three principles

Store: It is a single data source and is read-only

It’s an Action that describes the change

Reducer: It is responsible for distributing and processing changes and ultimately returning new data to the Store

API

creatorStore

Creating a Store object

appleMiddleware

Using middleware will be covered in the next lecture on middleware

bindActionCreators

This Api is used to bind actions to Dispatches so that components are unaware of the presence of Redux

const { dispatch } = useDispatch();
const _bindActionCreators = bindActionCreators(
  {
    // Define some actionCreators
    addCounter,
    subCounter,
  },
  dispatch
);

// Then you can issue an action
_bindActionCreators.addCounter();
Copy the code

combineReducers

As our pages become more and more complex we may need to split the different stores for the modules

This Api is going to help us recombine these stores into one Store

connect

Used to map Store and Action to the props of the component

compose

Compose is a method in functional programming that combines multiple functions from right to left

This article is just a primer on Redux, so the compose function can be explored in functional programming

Redux DevTools

This is a Chrome plugin that allows us to debug our Redux better

react-redux

This is a component library for connecting your components to Redux more easily

Use the following

import { Provider, useDispatch, useSelector } from 'react-redux';

<Provider store={store}>
  <A />
  <B />
  <C />
</Provider>;
Copy the code

So components A, B, and C have the ability to get data from the Store

See the following Demo for details

🌰

Here I’ll run through Redux quickly with a counter’s 🌰

Let’s start by creating our store

// Import the core API to create a Store
import { createStore } from 'redux';

export interface IStore {
  count: number;
}

export interface IAction {
  type: string;
  [key: string] :any;
}

// Define our Action Type
enum ACTION_TYPE {
  ADD_COUNTER = 'ADD_COUNTER',
  SUB_COUNTER = 'SUB_COUNTER',}// Expose Action Creators for the component call
export const addCounter = (payload: number) = > ({
  type: ACTION_TYPE.ADD_COUNTER,
  payload,
});

export const subCounter = (payload: number) = > ({
  type: ACTION_TYPE.SUB_COUNTER,
  payload,
});

// Create an initialized Store
const initStore: IStore = {
  count: 0};Create a Reducer to manage the actions sent by the View
const reducer = (store = initStore, action: IAction) = > {
  switch (action.type) {
    case ACTION_TYPE.ADD_COUNTER:
      return { ...store, count: store.count + action.payload };
    case ACTION_TYPE.SUB_COUNTER:
      return { ...store, count: store.count - action.payload };
    default:
      returnstore; }};Here we also have Redux DEVTools enabled
export const store = createStore(
  reducer,
  (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__()
);
Copy the code

The code for the view layer is as follows

import { useState } from 'react';
import { Button, Input } from 'antd';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { store, addCounter, subCounter, IStore } from './store';

function Counter() {
  // Get the data in Store
  const { count } = useSelector((store: IStore) = > store);
  const dispatch = useDispatch();
  const [payload, setPayload] = useState<number> (1);

  return (
    <>
      <Input
        value={payload}
        onChange={(v)= > setPayload(parseInt(v.target.value))}
      />
      <Button onClick={()= > dispatch(addCounter(payload))}>+</Button>
      <Button>{count}</Button>
      <Button onClick={()= > dispatch(subCounter(payload))}>-</Button>
    </>
  );
}

export default function Root() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}
Copy the code

thinking

The reducers in this article are synchronous code and what if we need to do something asynchronous when we send an action

Can asynchronous operations be handled in reducer?