Skip to content

Redux

redux原理

action

动作的对象, 传递两个属性

js
{ type'ADD_STUDENT',data:{name: 'tom',age:18} }
  • type: 要执行动作的标识符, 值为字符串且必须
  • data: 数据体,任意类型且非必填

reducer

用于初始化状态、加工状态。加工时,根据旧的 stateaction, 产生新的 state纯函数

TIP

reducer 由 store 自动触发首次调用,传递的 preState 为 undefined, action 为 {type: '@@REDUX/ININT_a.5.v.9'}

store

stateactionreducer联系在一起的对象

js
import { createStore } from "redux";
// 整合所有 reducer 的汇总
import reducer from "./reducers";
// 创建一个 store来存放应用共用状态
const store = createStore(reducer);

创建的 store 拥有三个 Api 属性:

  • getState(): 获取状态 state
  • dispatch(action): 分发action, 触发reducer调用, 产生新的state
  • subscribe(listener): 注册监听, 当产生了新的state时, 自动调用

combineReducers()

合并多个reducer 函数

js
import { combineReducers } from "redux";

import count from "./count";
import persons from "./person";

// 汇总所有reducer为一个总的reducer
export default combineReducers({
  count,
  persons,
});

基本应用

src 目录文件结构

text
src
├── redux
│   ├── constant.js  #action对象中type类型的常量
│   ├── count_reducer.js  #reducer函数
│   ├── count_action.js  #action对象
│   └── store.js  #全局唯一store对象
└── components
    └── Count.jsx  #Count组件
  • App.jsx
jsx
import React, { Component } from "react";
import Count from "./components/Count";

export default class App extends Component {
  render() {
    return (
      <div>
        <Count />
      </div>
    );
  }
}
  • index.js
js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./redux/store";

ReactDOM.render(<App />, document.getElementById("root"));
// 状态改变重新渲染 App 组件
store.subscribe(() => {
  ReactDOM.render(<App />, document.getElementById("root"));
});
  • constant.js
js
/* 该模块用于定义action对象中type类型的常量值,目的便于管理,同时防止单词写错 */
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
  • count_reducer.js
js
/*
 * 1.该文件是用于创建一个为Count组件服务的reducer,本质是一个函数
 * 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
 */
import { INCREMENT, DECREMENT } from "./constant";

const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {
  //从action对象中获取:type、data
  const { type, data } = action;
  //根据type决定如何加工数据
  switch (type) {
    case INCREMENT: //如果是加
      return preState + data;
    case DECREMENT: //若果是减
      return preState - data;
    default:
      return preState;
  }
}
  • count_action.js
js
/* 该文件专门为Count组件生成action对象 */
import { INCREMENT, DECREMENT } from "./constant";

export const createIncrementAction = (data) => ({ type: INCREMENT, data });
export const createDecrementAction = (data) => ({ type: DECREMENT, data });
  • store.js
js
/* 该文件用于暴露一个store对象,整个应用只有一个store对象 */

//引入createStore,创建store对象
import { createStore } from "redux";
//引入为Count组件服务的reducer
import countReducer from "./count_reducer";
//暴露store
export default createStore(countReducer);
  • Count.js
jsx
import React, { Component } from "react";
//引入store,用于获取redux中保存状态
import store from "@/redux/store";
//引入actionCreator,专门用于创建action对象
import { createIncrementAction, createDecrementAction } from "@/redux/count_action";

export default class Count extends Component {
  //检测redux中状态的变化,只要变化,就调用render
  //  componentDidMount(){
  // store.subscribe(()=>{
  // this.setState({})
  // })
  // }

  //加法
  increment = () => {
    store.dispatch(createIncrementAction(2));
  };
  //减法
  decrement = () => {
    store.dispatch(createDecrementAction(2));
  };
  //异步加
  incrementAsync = () => {
    setTimeout(() => {
      store.dispatch(createIncrementAction(2));
    }, 500);
  };

  render() {
    return (
      <div>
        {/* 获取state状态值 */}
        <h1>当前求和为:{store.getState()}</h1>
        <button onClick={this.increment}>+</button>&nbsp;
        <button onClick={this.decrement}>-</button>&nbsp;
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    );
  }
}

Redux 异步编程

异步操作交给 store 处理, 不在组件中操作

shell
# 异步中间件
npm install redux-thunk -S
  • 返回异步 action
js
// count_action.js
import { INCREMENT, DECREMENT } from "./constant.js";
//同步action,就是指action的值为Object类型的一般对象
export const createIncrementAction = (data) => ({ type: INCREMENT, data });
export const createDecrementAction = (data) => ({ type: DECREMENT, data });

//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
export const createIncrementAsyncAction = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data));
    }, time);
  };
};
  • 引入redux-thunk,用于支持异步 action
js
// store.js
import { createStore, applyMiddleware } from "redux";
import countReducer from "./count_reducer";
import thunk from "redux-thunk";

export default createStore(countReducer, applyMiddleware(thunk));
  • 组件内调用
js
// Count.jsx

//...
// incrementAsync = () => {
//     setTimeout(() => {
//       store.dispatch(createIncrementAction(2));
//     }, 500);
//   };

incrementAsync = () => {
  store.dispatch(createIncrementAsyncAction(1));
};
//...