仿写 redux 源码(二)

157 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

前情回顾

  • 前面一篇文章我们介绍了 redux 是用来干什么的,redux 的数据流向,以及 redux 创建 store 的方法
  • 下面来介绍 redux 在 react 中的使用

demo

import React, { Component } from "react";
import { store } from "./store";

export class MyReduxPage extends Component {
  componentDidMount() {
    this.unsubscribe = store.subscribe(() => {
      this.forceUpdate();
    });
  }
  
  componentWillUnmount() {
    this.unsubscribe();
  }
  
  handleAdd = () => store.dispatch({ type: "ADD", payload: 100 });
  
  
  setNum = () => {
    store.dispatch({ type: "ADD2", payload: 10 });
  };
  
  render() {    
    return (
      <div>
        <h2>my-redux-demo</h2>
        <button onClick={this.handleAdd}>ADD:{store.getState()}</button>
        <br />
      </div>
    );
  }
}
  • 上面的代码中,我们通过 store.getState() 获取 store 中的状态数据
  • 通过给 handleAdd 来改变 store 中的数据,其中 store.dispatch 则是 redux 提供的提交状态变更的方法,它接受的纯对象就是 action
  • 我们需要在数据变更之后更新试图,因此在 componentDidMount 中使用 store.subscribe 注册一个让当前组件更新的方法,有注册就会有注销,在 redux 中 store.subscribe 会返回一个注销订阅更新的方法,需要在组件卸载时执行,因此需要在 componentWillUnmount 中调用 this.unsubscribe 方法以完成注销订阅更新

dispatch 的扩展

  • 上面的例子中,只展示了原始 dispatch 的功能
  • 如果遇到需要异步变更数据的需求,那么以上的 diaptch 就不再适用了
  • 好在 redux 提供了增强 dispatch 能力的接口,就是 createStore 的第三个参数 enhancer
  • 它就是 applyMiddleware 执行的结果,applyMiddleware 会根据接受的中间件的功能来增强 dispatch 的能力,如:redux-thunk,能让增强后的 dipatch 支持接受一个函数,并且此函数接受原始的 dispatch,那么我们可以使用回掉的方式解决上面提到的,异步变更数据的需求了
  handleAsyncAdd = () => {
    // 用 setTimeout 模拟 ajax 请求
    // 
    // 1、直接在组件中写 ajax 请求
    // 非常不优雅
    // setTimeout(() => {
    //   store.dispatch({ type: "ADD", payload: 100 });
    // }, 1000);
    
    // 2、将数据请求函数抽出去
    // 让 store.dispatch 直接调用,这样就可以将数据请求与视图渲染分离开
    store.dispatch((dispatch) => {
      setTimeout(() => {
        dispatch({ type: "ADD", payload: 100 });
      }, 1000);
    });
  };
  • 在上面的代码中,store.dispatch 就是增强后的,其可以接受一个函数为参数,并且这个函数接受的是原始的 dispatch,当异步任务 setTimeout 到期之后,执行原始的 dispatch 以改变数据

  • 同样的也可以让增强 dispatch 的能力以支持 Promise,代码如下

  handlePromiseAdd = () => {
    store.dispatch({
      type: "ADD",
      payload: Promise.resolve(100),
    });
  };

小结

  • 本文介绍了 redux 的基本使用,下篇文章将介绍 redux 的实现原理

  • 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏

  • 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰