React Foundation Consolidation (32) - Three Principles of Redux
1. Three principles of Redux
-
single source of truth
- The state of the entire application is stored in an object tree, and this object tree is only stored in one store;
- Redux does not force us not to create multiple Stores, but doing so is not conducive to data maintenance;
- A single data source can make the state of the entire application easy to maintain, track, and modify;
-
State is read-only
-
The only way to modify the State must be to trigger an action, do not try to modify the State in any other way;
-
This ensures that neither View nor network requests can directly modify the state, they can only describe how they want to modify the state through actions;
-
This can ensure that all modifications are processed centrally and executed in strict order, so there is no need to worry about reace conditions (race conditions);
-
-
Use pure functions to perform modifications
- Connect the old state and actions through reducer, and return a new state;
- As the complexity of the application increases, we can split the reducer into multiple small reducers to operate part of different state trees respectively;
- But all reducers should be pure functions without any side effects;
2. The process of using Redux
3. The basic use of Redux (counter small case)
-
build react project
# 创建新的react项目 create-react-app redux-learn # 创建成功后cd进入文件夹,随后安装redux npm install redux
-
Delete temporarily irrelevant files, build store-related files, and reference the store to the required page
- Table of contents
-
store/constants.js
export const ADD_NUMBER = "add_number"; export const SUB_NUMBER = "sub_number";
-
store/reducer.js
import * as actionTypes from "./constants"; const initialState = { counter: 111, }; function reducer(state = initialState, action) { switch (action.type) { case actionTypes.ADD_NUMBER: return { ...state, counter: state.counter + action.num }; case actionTypes.SUB_NUMBER: return { ...state, counter: state.counter - action.num }; default: return state; } } export default reducer;
-
store/actionCreators.js
import * as actionTypes from "./constants"; export const addNumberAction = (num) => ({ type: actionTypes.ADD_NUMBER, num, }); export const subNumberAction = (num) => ({ type: actionTypes.SUB_NUMBER, num, });
-
store/index.js
import { createStore } from "redux"; import reducer from "./reducer"; const store = createStore(reducer); export default store;
-
pages/home.jsx
import React, { PureComponent } from "react"; import store from "../store"; import { addNumberAction } from "../store/actionCreators"; export class home extends PureComponent { constructor() { super(); this.state = { counter: store.getState().counter, }; } componentDidMount() { store.subscribe(() => { const state = store.getState(); this.setState({ counter: state.counter, }); }); } addNumber(num) { store.dispatch(addNumberAction(num)); } render() { const { counter } = this.state; return ( <div> home counter:{ counter} <div> <button onClick={ (e) => this.addNumber(1)}>+1</button> <button onClick={ (e) => this.addNumber(5)}>+5</button> <button onClick={ (e) => this.addNumber(8)}>+8</button> </div> </div> ); } } export default home;
-
pages/profile.jsx
import React, { PureComponent } from "react"; import store from "../store"; import { subNumberAction } from "../store/actionCreators"; export class profile extends PureComponent { constructor() { super(); this.state = { counter: store.getState().counter, }; } componentDidMount() { store.subscribe(() => { const state = store.getState(); this.setState({ counter: state.counter, }); }); } subNumber(num) { store.dispatch(subNumberAction(num)); } render() { const { counter } = this.state; return ( <div> profile counter:{ counter} <div> <button onClick={ (e) => this.subNumber(1)}>-1</button> <button onClick={ (e) => this.subNumber(5)}>-5</button> <button onClick={ (e) => this.subNumber(8)}>-8</button> </div> </div> ); } } export default profile;
-
App.jsx
import React, { PureComponent } from "react"; import Home from "./pages/home"; import Profile from "./pages/profile"; import "./style.css"; import store from "./store"; export class App extends PureComponent { constructor() { super(); this.state = { counter: store.getState().counter, }; } componentDidMount() { store.subscribe(() => { const state = store.getState(); this.setState({ counter: state.counter, }); }); } render() { const { counter } = this.state; return ( <div> <h2>App Counter: { counter}</h2> <div className="pages"> <Home /> <Profile /> </div> </div> ); } } export default App;
- operation result
So far, the code is still relatively complicated, and the code will be optimized in React Foundation Consolidation (33)