前言
React通过reduxjs/redux实现状态管理
下载依赖
定义Store
定义Action常量
src/store/constants.js1
| export const CHANGE_KEY = "changeKey";
|
定义Reducer
src/store/reducer.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import * as actionTypes from "./constants";
const initialState = { key: "default" };
function reducer(state = initialState, action) { switch (action.type) { case actionTypes.CHANGE_KEY: const objCopy = Object.assign({}, state, {}); objCopy.key = action.payload; return objCopy; default: return state; } }
export default reducer;
|
创建Store
src/store/index.js1 2 3 4 5 6
| import { createStore } from "redux"; import reducer from "./reducer";
const store = createStore(reducer);
export default store;
|
获取数据
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import React from "react"; import store from "./store/index.js";
export class Component extends React.Component { constructor() { super(); this.state = { key: store.getState().key }; }
componentDidMount() { store.subscribe(() => { this.setState({ key: store.getState().key }); }); }
componentWillUnmount() { store.unsubscribe(); }
render() { return ( <> { this.state.key } </> ); } }
|
修改数据
定义Action对象
src/store/actionCreator.js1 2 3 4 5 6
| import * as actionTypes from "./constants";
export const changeKey = (payload) => ({ type: actionTypes.CHANGE_KEY, payload });
|
派发事件
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React from "react"; import store from "./store/index.js"; import { changeKey } from "./store/actionCreator";
export class Component extends React.Component { constructor() { super(); this.fn = this.fn.bind(this); } fn() { store.dispatch(changeKey("value")); }
render() { return ( <> <button onClick={ this.fn }></button> </> ); } }
|
通过react-redux实现自动映射
- 通过react-redux实现自动映射Redux的state到组件的props
下载依赖
通过Provider组件包裹根组件
src/index.js1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import ReactDOM from "react-dom"; import App from "./App.jsx"; import { Provider } from "react-redux"; import store from "./store/index.js";
const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <React.StrictMode> <Provider store={ store }> <App /> </Provider> </React.StrictMode> );
|
获取数据
- 通过
mapStateToProps()的第一个参数,映射Redux的state到props
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react"; import { connect } from "react-redux";
class Component extends React.Component { constructor() { super(); } render() { return ( <> { this.props.key } </> ); } }
const mapStateToProps = (state) => ({ key: state.key });
export default connect(mapStateToProps)(Component);
|
修改数据
- 通过
mapStateToProps()的第二个参数,映射Redux的dispatch到props
定义Action对象
src/store/actionCreator.js1 2 3 4 5 6
| import * as actionTypes from "./constants";
export const changeKey = (payload) => ({ type: actionTypes.CHANGE_KEY, payload });
|
派发事件
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import React from "react"; import { connect } from "react-redux"; import { changeKey } from "./store/actionCreator";
class Component extends React.Component { constructor() { super();
this.fn = this.fn.bind(this); }
fn() { store.dispatch(changeKey("value")); } render() { return ( <> <button onClick={ this.fn }></button> </> ); } }
const mapDispatchToProps = (dispatch) => ({ changeKey: (payload) => dispatch(changeKey(payload)); })
export default connect(null, mapDispatchToProps)(Component);
|
通过react-thunk实现异步操作
- 默认
dispatch()方法只能传递对象作为参数
- 通过react-thunk实现
dispatch()方法传递函数作为参数
下载依赖
1
| npm install react-thunk axios
|
应用中间件
src/store/index.js1 2 3 4 5 6 7
| import { createStore } from "redux"; import reducer from "./reducer"; import thunk from "react-thunk";
const store = createStore(reducer, applyMiddleware(thunk));
export default store;
|
修改数据
定义Action函数
src/store/actionCreator.js1 2 3 4 5 6 7 8 9 10
| import * as actionTypes from "./constants"; import axios from "axios";
export const changeKey = (payload) => { return (dispatch, getState) => { axios.get("https://example.com").then(res => { dispatch(changeKey(res.data)); }); } };
|
派发事件
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import React from "react"; import { connect } from "react-redux"; import { changeKey } from "./store/actionCreator";
class Component extends React.Component { constructor() { super();
this.fn = this.fn.bind(this); }
fn() { store.dispatch(changeKey("value")); } render() { return ( <> <button onClick={ this.fn }></button> </> ); } }
const mapDispatchToProps = (dispatch) => ({ changeKey: (payload) => dispatch(changeKey(payload)); })
export default connect(null, mapDispatchToProps)(Component);
|
拆分模块
定义Store
分模块定义Action常量
src/store/constants-1.js1
| export const REDUCER1_CHANGE_KEY = "reducer1ChangeKey";
|
src/store/constants-2.js1
| export const REDUCER2_CHANGE_KEY = "reducer2ChangeKey";
|
分模块定义Reducer
src/store/reducer-1.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import * as actionTypes from "./constants-1";
const initialState = { key: "default" };
function reducer(state = initialState, action) { switch (action.type) { case actionTypes.REDUCER1_CHANGE_KEY: const objCopy = Object.assign({}, state, {}); objCopy.key = action.payload; return objCopy; default: return state; } }
export default reducer;
|
src/store/reducer-2.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import * as actionTypes from "./constants-2";
const initialState = { key: "default" };
function reducer(state = initialState, action) { switch (action.type) { case actionTypes.REDUCER2_CHANGE_KEY: const objCopy = Object.assign({}, state, {}); objCopy.key = action.payload; return objCopy; default: return state; } }
export default reducer;
|
创建Store
- 通过
combineReducers()合并多个Reducer
src/store/index.js1 2 3 4 5 6 7 8 9 10 11 12
| import { createStore, combineReducers } from "redux"; import reducer1 from "./reducer-1"; import reducer2 from "./reducer-2";
const reducer = combineReducers({ reducer1: reducer1, reducer2: reducer2 });
const store = createStore(reducer);
export default store;
|
获取指定模块的数据
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import React from "react"; import store from "./store/index.js";
export class Component extends React.Component { constructor() { super(); this.state = { key: store.getState().reducer1.key }; }
componentDidMount() { store.subscribe(() => { this.setState({ key: store.getState().reducer1.key }); }); }
componentWillUnmount() { store.unsubscribe(); }
render() { return ( <> { this.state.key } </> ); } }
|
修改指定模块的数据
定义Action对象
src/store/actionCreator.js1 2 3 4 5 6
| import * as actionTypes from "./constants";
export const reducer1ChangeKey = (payload) => ({ type: actionTypes.REDUCER1_CHANGE_KEY, payload });
|
派发事件
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React from "react"; import store from "./store/index.js"; import { reducer1ChangeKey } from "./store/actionCreator";
export class Component extends React.Component { constructor() { super(); this.fn = this.fn.bind(this); } fn() { store.dispatch(reducer1ChangeKey("value")); }
render() { return ( <> <button onClick={ this.fn }></button> </> ); } }
|
下载依赖
1
| npm install @reduxjs/toolkit axios
|
定义Store
分模块定义Reducer
src/store/reducer-1.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { createSlice } from "@reduxjs/toolkit";
const reducerSlice = createSlice({ name: "reducer1", initialState: { key: "default" }, reducers: { reducer1ChangeKey: (state, action) => { state.key = action.payload; } } });
export const { reducer1ChangeKey } = reducerSlice.actions;
export default reducerSlice.reducer;
|
src/store/reducer-2.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { createSlice } from "@reduxjs/toolkit";
const reducerSlice = createSlice({ name: "reducer2", initialState: { key: "default" }, reducers: { reducer2ChangeKey: (state, action) => { state.key = action.payload; } } });
export const { reducer2ChangeKey } = reducerSlice.actions;
export default reducerSlice.reducer;
|
创建Store
src/store/index.js1 2 3 4 5 6 7 8 9 10 11 12
| import { configureStore } from "@reduxjs/toolkit"; import reducer1 from "./reducer-1"; import reducer2 from "./reducer-2";
const store = configureStore({ reducer: { reducer1: reducer1, reducer2: reducer2 }, });
export default store;
|
获取指定模块的数据
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import React from "react"; import store from "./store/index.js";
export class Component extends React.Component { constructor() { super(); this.state = { key: store.getState().reducer1.key }; }
componentDidMount() { store.subscribe(() => { this.setState({ key: store.getState().reducer1.key }); }); }
componentWillUnmount() { store.unsubscribe(); }
render() { return ( <> { this.state.key } </> ); } }
|
修改指定模块的数据
src/Component.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React from "react"; import store from "./store/index.js"; import { reducer1ChangeKey } from "./store/reducer-1";
export class Component extends React.Component { constructor() { super(); this.fn = this.fn.bind(this); } fn() { store.dispatch(reducer1ChangeKey("value")); }
render() { return ( <> <button onClick={ this.fn }></button> </> ); } }
|
异步操作
直接通过派发事件修改数据
src/store/reducer.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
createAsyncThunk("fetchData", async (extraData, store) => { const res = await axios.get("https://example.com"); store.dispatch(reducerChangeKey(res.data)); });
const reducerSlice = createSlice({ name: "reducer", initialState: { key: "default" }, reducers: { reducerChangeKey: (state, action) => { state.key = action.payload; } } });
export default reducerSlice.reducer;
|
通过计算属性名监听异步操作状态
src/store/reducer.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
const fetchData = createAsyncThunk("fetchData", async (extraData, store) => { const res = await axios.get("https://example.com"); return res.data; });
const reducerSlice = createSlice({ name: "reducer", initialState: { key: "default" }, extraReducers: { [fetchData.padding]: (state, action) => { ... }, [fetchData.fulfilled]: (state, action) => { state.key = action.payload; }, [fetchData.rejected]: (state, action) => { ... } } });
export default reducerSlice.reducer;
|
通过链式调用监听异步操作状态
src/store/reducer.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
const fetchData = createAsyncThunk("fetchData", async (extraData, store) => { const res = await axios.get("https://example.com"); return res.data; });
const reducerSlice = createSlice({ name: "reducer", initialState: { key: "default" }, extraReducers: (builder) => { builder.addCase(fetchData.padding, (state, action) => { ... }).addCase(fetchData.fulfilled, (state, action) => { state.key = action.payload; }).addCase(fetchData.rejected, (state, action) => { ... }); } });
export default reducerSlice.reducer;
|
完成