Skip to content

Redux

作用

集中式管理 react、vue、angular 等应用中多个组件的状态,是一个库,不单单可用于 react,只是更多的用于 react 中

模型图

三个核心

action

  1. 作用:action 是把数据从应用传到 store 的有效载荷,是 store 数据的唯一来源
  2. 创建
javascript
import { INCREMENT, DECREMENT } from "./constant";

export const incrementAction = (data) => {
  return { type: INCREMENT, data };
};

export const decrementAction = (data) => {
  return { type: DECREMENT, data };
};
  1. 页面上的使用:通过分发 action 操作数据
javascript
import { incrementAction, decrementAction } from "./redux/actions";

export default class index extends Component {
  increment = () => {
    const { value } = this.selectNumber;
    store.dispatch(incrementAction(value));
  };
}
  1. 异步 action:同步 action 中返回值为对象,而异步 action 中返回值为函数,其中一般会调用同步 action
javascript
export const incrementAsyncAction = (data, delay) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(incrementAction(data));
    }, delay);
  };
};

reducer

  1. 作用:reducer 指定了应用状态的变化如何响应 action 并发送到 store 中
  2. 特征:本质是一个纯函数,接收两个参数,之前的状态(preState)、动作对象(action)。第一次被调用时,preState 为 undefined
  3. 创建
javascript
import { ADD_PERSON } from "../constant";

export default function personReducer(preState, action) {
  if (preState === undefined) {
    preState = [
      {
        id: "001",
        name: "Tom",
        age: 23,
      },
    ];
  }

  // 从action中取出type和data
  const { type, data } = action;

  switch (type) {
    case ADD_PERSON:
      // 没有对preState进行push或unshift操作,因为redux默认若返回值和之前状态一致,则不更新页面
      return [data, ...preState];
    default:
      return preState;
  }
}
  1. 纯函数 只要是同样的输入,必定得到同样的输出。遵循以下约束
  • 不得改写参数
  • 不能调用 I/O 的 API
  • 不能调用 Date.new()或者 Math.random()等不纯的方法,因为每次会得到不一样的结果

store

  1. 作用:将 action 和 reducer 联系在一起,维持应用中的状态

  2. 特征:一个应用只有一个 store。当需要拆分数据处理逻辑时,应该使用多个 reducer

  3. 创建

    javascript
    import { legacy_createStore } from "redux";
    import countReducer from "./reducer";
    
    export default legacy_createStore(countReducer);

    当使用异步 action 后,需对 store 进行修改,使用 redux-thunk 和中间件支持异步 action,修改后的 store 文件如下:

    javascript
    import { legacy_createStore, applyMiddleware } from "redux";
    // 用于支持异步action
    import thunk from "redux-thunk";
    import countReducer from "./reducer";
    
    export default legacy_createStore(countReducer, applyMiddleware(thunk));
  4. 页面上取值:

javascript
render() {
 return (
   <div>
     <h1>当前求和为{store.getState()}</h1>&nbsp;
   </div>
 )
}

react-redux

定义

react-redux 其实是 Redux 的官方 React 绑定库,其中封装了一些 Redux 与 React 连接的操作,可以是 Redux 的使用更加简单

模型图

规则

  1. 所有的 UI 组件被一个容器组件包裹,它们是父子关系
  2. UI 组件不与 Redux 进行操作,而是由容器组件与 Redux 进行操作,可以使用 Redux 的任意 api
  3. 容器组件会传给 UI 组件如下数据:
    1. 状态,即 mapStateToProps()
    2. 操作状态的方法,即 mapDispatchToProps()

基础使用(见 04-react-redux 基础使用)

建立容器组件时的注意点

  1. 容器组件与 UI 组件通过 react-redux 中的 connect 进行连接,传递 mapStateToProps 和 mapDispatchToProps
  2. mapStateToProps()
    1. 用于传递状态
    2. 返回一个对象
    3. react-redux 在调用该函数时已经传入了 state
    4. 此处的值传入 UI 组件中,UI 组件可使用 this.props.xxx 拿到对应的值
    5. 用到的 store 在根目录中通过 Provider 包裹 App 组件并传入 store 的方式获取
      javascript
      const root = ReactDOM.createRoot(document.getElementById("root"));
      root.render(
        <React.StrictMode>
          <Provider store={store}>
            <App />
          </Provider>
        </React.StrictMode>
      );
  3. mapDispatchToProps()
    1. 用于传递操作状态的方法
    2. 返回一个对象,对象的 key 自定义,value 是一个方法
    3. 注意简写方式

建立 UI 组件时的注意点

  1. 不直接参与 Redux 的使用
  2. 使用 this.props.xxx 拿到容器组件传来对应的值

融合 UI 组件与容器组件

开发时将 UI 组件与容器组件进行融合后放到一个文件中(见,05-融合 UI 组件与容器组件)

多个组件间的数据共享(重要,见 06-react-redux 数据共享)

  1. 完善各个组件的 action 和 reducer
  2. 合并 reducer,如下
javascript
import { combineReducers } from "redux";
import countReducer from "./reducers/count";
import personReducer from "./reducers/person";

/**
 * 合并Reducer
 * 使用combineReducers合并Reducer,key为自定义,value为reducer
 */
export default allReducer = combineReducers({
  count: countReducer,
  persons: personReducer,
});

注意:合并 reducer 后导致 state 变化,变为一个新的对象,对于组件 mapStateToProps 中对应的 state 需要通过.属性的方式取到 3. 修改 store,使用合并后的 reducer

javascript
import { legacy_createStore, applyMiddleware } from "redux";
// 用于支持异步action
import thunk from "redux-thunk";
// 合并后的reducer
import allReducer from "./reducers/index";

export default legacy_createStore(allReducer, applyMiddleware(thunk));