美文网首页ReactRedux
从 Redux 到 React-Redux

从 Redux 到 React-Redux

作者: 柏丘君 | 来源:发表于2017-06-01 17:53 被阅读202次

上篇文章中,我们用 React 结合 Redux 实现了一个小计算器,并将组件拆分为容器组件和木偶组件,本文再基于这个例子继续做一些拓展,并最终引出 React-Redux。

计算器应用的问题

对于计算器小应用,我们已经实现了其所有的功能,因此不再有功能上的问题了,那么还有没有可以优化的地方呢?当然。
在这个例子中,每个容器组件都会引入 store,这样会产生两个问题:

  • 每个容器组件都去引入 store,有点麻烦
  • 如果我们要写一个插件提供给别人使用,但是并不知道别人的 store 的引用路径,这就有点难办了

或许你会想:如果有个全局变量就好了,将 store 存放在全局变量中,就不用每次都引入了,也不用关心 store 的引用路径了。
那么可不可以提供一个最外层的组件,让其提供 store 对象,然后子组件直接去取用这个对象呢?当然可以。这里就需要用到我们前面说过的 context,可以在这篇文章中查看相应的内容。

context 回顾

context 是组件树上的一个全局属性,这里先回顾一下 context 的使用:

  • 父级需要声明自己支持 context,并提供一个 getChildContext 函数返回初始 context
  • 子组件需要声明自己需要使用 context
  • 子组件取用 context 中的属性时,属性验证(PropTypes)必须和父组件中的声明保持一致
  • 若子组件拥有构造函数(constructor),需要将 context 传入该构造函数,并在 super 调用父类构造函数时一并传入
  • 可以使用 super(...args) 来代替 super(props,context)

定义 Provider 组件

下面,我们来定义一个 Provider 组件,用来在 context 中存放 store 对象,新建一个 Provider.js 文件:

import React,{ Component } from "react";
import PropTypes from "prop-types";

export default class Provider extends Component{
    // 声明 context 属性的类型
    static childContextTypes = {
        store:PropTypes.object.isRequired,
    }

    // 返回初始的 context
    getChildContext(){
        return{
            // store 对象由 Provider 组建的 props 传入
            store:this.props.store,
        }
    }

    render(){
        // 直接渲染子节点
        return this.props.children;
    }
}

修改 App.js,让 Provider 作为组件树的根节点,并向其传入 store:

import React,{ Component } from "react";
import Counter from "./ContainerCounter";
import Provider from "./Provider";
import store from "./Store/store";

export default class App extends Component{
    render(){
        return(
            <Provider store = { store }>
                <Counter />
            </Provider>
        );
    }
}

修改 ContainerCounter.js,从 context 中获取 store:

import React,{ Component } from "react";
import PropTypes from "prop-types";
import ACTIONS from "./Store/actions";
import UICounter from "./UICounter";

export default class ContainerCounter extends Component{
    // 声明自己需要取用 context 属性
    static contextTypes = {
        store:PropTypes.object.isRequired,
    }

    constructor(props,context) {
        super(props,context);
        // 获取初始状态
        this.state = {
            // 使用 this.context.store 代替原先的 store
            value:this.context.store.getState().value,
        };
    }

    componentWillMount() {
        // 监听 store 变化
        this.context.store.subscribe(this.watchStore.bind(this));
    }

    componentWillUnmount() {
        // 对 store 变化取消监听
        this.context.store.unsubscribe(this.watchStore.bind(this));
    }

    // 监听回调函数,当 store 变化后执行
    watchStore(){
        // 回调函数中重新设置状态
        this.setState(this.getCurrentState());
    }

    // 从 store 中获取状态
    getCurrentState(){
        return{
            value:this.context.store.getState().value,
        }
    }

    // 增加函数
    increase(){
        // 派发 INCREMENT Action
        this.context.store.dispatch(ACTIONS.increament());
    }

    // 减少函数
    decrease(){
        // 派发 DECREAMENT Action
        this.context.store.dispatch(ACTIONS.decreament());
    }

    render(){
        return(
            <UICounter
                increase = { this.increase.bind(this)}
                decrease = { this.decrease.bind(this)}
                value = { this.state.value }
            />
        );
    }
}

效果和原先保持一致:

利用 context 获取 store.gif

使用 React-Redux

通过前面的例子,我们对应用进行了如下改进:

  • 将组件拆分为容器组件和木偶组件
  • 使用 Provider 顶层组件,通过 context 提供 store

前面说到,Redux 作为一款状态管理工具,可以和任意的框架结合使用,当然,还有一个更加适用于 React 开发的 React-Redux 库。其所作的工作和我们前面的差不多,但增加了不少的易用性。使用 React-Redux 前需要先进行安装:

npm install --save react-redux

下面说一下 React-Redux 库中的两个概念:

  • connect:用来连接木偶组件,并转换为容器组件,是的,我们不需要自己写容器组件了
  • Provider 组件:顶层组件,通过 context 提供 store

connect 函数接受两个参数,这两个参数都是函数:

  • mapStateToProps:从 store 中获取值,并传递给木偶组件
  • mapDispatchToProps:定义回调函数,并将这些回调函数传递给木偶组件,木偶组件调用通过这些函数向 store 派发 action

下面看一下代码实现:
App.js:

import React,{ Component } from "react";
import Counter from "./ContainerCounter";
// 从 react-redux 中引入 Provider 组件
import { Provider } from "react-redux";
import store from "./Store/store";

export default class App extends Component{
    render(){
        return(
            <Provider store = { store }>
                <Counter />
            </Provider>
        );
    }
}

ContainerCounter.js:

import { connect } from "react-redux";
import ACTIONS from "./Store/actions";
import UICounter from "./UICounter";

function mapStateToProps(state){
    return{
        value:state.value
    }
}

function mapDispatchToProps(dispatch){
    return{
        // 增加
        increase(){
            // 派发 action
            dispatch(ACTIONS.increament());
        },
        // 减少
        decrease(){
            dispatch(ACTIONS.decreament());
        }
    }
}

const ContainerCounter = connect(
    mapStateToProps,
    mapDispatchToProps,
)(UICounter);

export default ContainerCounter;

最终效果和前面一样。
可见,使用 react-redux 后,逻辑变得更加清晰了,也减少了许多操作,比如对 store 进行监听(subscribe),声明子组件的 context 等。这些事情 react-redux 都帮我们做了,我们只需定义两个函数(mapStateToProps,mapDispatchToProps)传递给 connect 函数,connect 函数调用的结果也是一个函数,我们再将木偶组件传入这个结果函数,就自动生成了容器组件。更易维护,代码量更少。
除此之外,react-redux 还进行了一些优化的处理,比如 shouldComponentUpdate 的优化等,但核心原理没有变,只是进行了一层封装处理。
因此,在使用 react-redux 之前,最好对 Redux 有一些了解,否则会因为不清楚内部的原理而成为代码搬运工。

总结

本文首先从全局 store 入手,构造了 Redux 版本的 Provider 组件,在此基础上引入了更加方便的 react-redux 库,更加适用于 React 开发,提升了开发效率和项目的可维护性。

完。

相关文章

  • 搞定 Mobx 小程序状态管理

    1. 前言 从vuex到 redux ,react-redux , pinia, 最后的Mobx全部都得搞;还好...

  • 从 Redux 到 React-Redux

    在上篇文章中,我们用 React 结合 Redux 实现了一个小计算器,并将组件拆分为容器组件和木偶组件,本文再基...

  • redux的简单应用

    1、安装 redux和react-redux: npm i redux react-redux --save-de...

  • React-redux概念学习

    React-redux 概述 react-redux 能够使你的React组件从React store中很方便的读...

  • React高级篇(二)Redux工作流(react-redux)

    在《React高级篇(一)从Flux到Redux,react-redux》文章中贴过一张redux单向数据流的图,...

  • react-redux

    redux 全局状态管理 react-redux 优化模块 优化redux的使用过程 通过react-redux ...

  • React(五)

    React-redux(三):connect和mapStateToProps React-redux(四):map...

  • react-redux

    使用react-redux,可以更方便的使用redux开发 先install react-redux使用react...

  • react-redux

    react-redux react-redux可以使redux的state成为组件的属性,dispatch的act...

  • react-redux

    一、什么是react-redux React-Redux是Redux的官方React绑定。 它允许您的React组...

网友评论

    本文标题:从 Redux 到 React-Redux

    本文链接:https://www.haomeiwen.com/subject/muuefxtx.html