Redux、react-redux、redux-thunk、immer

123 阅读2分钟

Redux

  • 架构思想,Redux 是遵循 Flux 架构设计而成的
  • 文档
  • 为什么使用 Redux
    • 跨多个组件同步共享数据的时候,方便管理数据
  • Redux 的使用原则
    • Single Source of Truth(唯一的数据源)
    • State is read-only(状态是只读的)
    • Changes are made with pure function(数据的改变必须通过纯函数完成)
  • 纯函数
    • 函数的执行结果是可预测的
    • 纯函数内不能发起异步请求
    • 纯函数里面不能返回随机数
  • Redux 核心概念
    • store 状态机板块

    • reducer 纯函数,根据用户提供的 action,生成对应的数据包给 store

    • action 本质是一个对象,用以描述用户的需求

      {
        type:'increment',  //用户具体需求,type是关键字
        payload:10  //可选参数
      }
      
  • dispatcher 派发器,负责将 action 传递给 reducer
  • view 视图层,项目 jsx 组件

Redux 的方法

  • var store = createStore(reducer) 创造状态机
  • store.getState() 让组件获取状态机的数据
  • store.dispatch(action) 让组件触发状态机的数据变化
  • store.subscribe(回调函数) 让组件及时知道状态机的最新数据变化,从而触发视图更新
  • 发布-订阅 模式
    • 发布,状态机发布最新数据
    • 订阅,组件内部只有订阅了状态机的发布动作,才能实时获取最新数据并渲染

使用

  • 安装yarn add redux
  • 新建 store/index.js 创建状态机对象
  • 新建 reducer/count.js 为状态机提供功能支撑
  • 在 Num.jsx 组件中,通过 store.getState() 获取状态机数据
  • 在 Btn.jsx 组件中,通过 store.dispatch() 触发状态机数据变化
  • 在 Num.jsx 组件中,通过 store.subscribe() 订阅状态机的数据变化,实时更新视图

Redux 跟 React 的关系

  • Redux 与 React ,两者并非强绑定关系
  • 我们可以在普通的 html 中使用 Redux

redux 与 react-redux 结合实现状态管理

react-redux 文档

使用

  • 安装
npm i react-redux
或者
yarn add react-redux
  • 在项目入口文件 index.js 中向根组件,注入状态机
import { Provider } from "react-redux"
import { store } from "./store/index"
<Provider store={store}>
  <App />
</Provider>
  • 提取并使用状态机数据

redux-thunk 实现异步 action

  • 安装yarn add redux-thunk
  • 在 store/index.js 中集成异步中间件
let store = createStore(
  reducer,
  applyMiddleware(thunk) //向状态机对象,集成中间件
)
export default store
  • 在 action/index.js 模块中,定义并实现异步 action
export const increAsync = (payload) => {
  return (dispatch) => {
    //异步action中的回调函数,会拦截dispatch
    setTimeout(() => {
      //模拟异步请求
      dispatch(increment()); //异步请求结束后,按需调用同步action
    }, 2000);
  };
};

immutable 或 immer 实现优化性能

不可变数据,避免对象引用问题

数据包定义后就成为了一种不可变的数据,后续对于该数据包的所有操作,其实都是在原数据包的基础之上,形成了一个新的差量化的拷贝

  • 安装 npm i immer
  • 使用
let obj = produce(state,(draft)=>{ //draft可以认为是state原数据包的一个拷贝
        draft.isLoading = true
      })
      console.log('开始登录',obj);