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?