当前位置: 首页 > news >正文

React-redux的原理以及使用

当一个react项目组件层级越来越深,页面越来越多的时候,数据在各个组件层级和页面之间传递的需求就会比较多,很多变量也需要做成可全局管理的。在这个时候,redux和react-redux的使用就很有必要了。它们能帮助我们很方便的进行项目全局性的数据管理。

下面,就写一下我自己对 reduxReact-redux 的学习以及使用的心得,权当是对学习过程的一种记录和分享。

一、redux和React-redux的几个重要概念

1.1 action

Action 是把数据从应用(这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。

1.2 reducer

Reducers 指定了应用状态的变化如何响应 actions并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

1.3 store

store就是把action和reducer联系到一起的对象,store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。
Redux 中,所有的数据(比如state)被保存在一个store容器中 ,在一个应用程序中只能有一个store对象。当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态。

1.4 Provider

Provider 其实就只是一个外层容器,它的作用就是通过配合 connect 来达到跨层级传递数据。使用时只需将Provider定义为整个项目最外层的组件,并设置好store。那么整个项目都可以直接获取这个store。它的原理其实是通过React中的[Context]()来实现的。它大致的核心代码如下:

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

export default class Provider extends Component {
    getChildContext() {
        return {store: this.props.store}
    }

    constructor() {
        super()

        this.state = {}
    }

    render() {
        return this.props.children
    }
}

Provider.childContextTypes = {
    store: PropTypes.object
}

1.5 connect

connect 的作用是连接React组件与 Redux store,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。

它共有四个参数mapStateToProps, mapDispatchToProps, mergeProps以及options。

mapStateToProps 的作用是将store里的state(数据源)绑定到指定组件的props中
mapDispatchToProps 的作用是将store里的action(操作数据的方法)绑定到指定组件的props中
另外两个方法一般情况下使用不到,这里就不做介绍。。

那么 connect 是怎么将React组件与 Redux store连接起来的呢?其主要逻辑可以总结成以下代码:

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

const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent => {
    class Connect extends Component {
        constructor() {
            super()

            this.state = {}

        }

        componentWillMount() {
            this.unSubscribe = this.context.store.subscribe(() => {
                this.setState(mapStateToProps(this.context.store.getState()))
            })
        }

        componentWillUnmount() {
            this.unSubscribe()
        }

        render() {
            return <WrappedComponent  {...this.state}
                                      {...mapDispatchToProps(this.context.store.dispatch)}/>
        }
    }

    Connect.contextTypes = {
        store: PropTypes.object
    }
    return Connect
})

export default connect

二、redux和React-redux的使用

项目中关于redux的文件夹目录如下
redux.png

拿管理用户信息数据的需求来举例

第一步,编写操作用户信息的action


import {USER_INFO} from "../constants/actionTypes";
import store from '../store/store'

export const switchUser = (data) => {
    console.log("switchUser()",data);
    return () => {
        store.dispatch({
            type: USER_INFO,
            ...data
        })
    }
}

第二步,编写改变用户信息并返回新state的reducer

import {USER_INFO} from "../constants/actionTypes";

const redUserInfo = (state = {
    userId: 10001,
    userName: '',
    userOpenid: '',
    userPhone: '',
    userRole: 0
}, action) => {
    if (action === undefined) {
        return state
    }

    switch (action.type) {
        case USER_INFO:
            return {
                ...state,
                ...action
            }
        default:
            return state
    }

}

第三步,完成store的创建

import {createStore} from 'redux'
import reducers from '../reducers/index'

let store = createStore(reducers)

export default store

第四步,获取用户信息

//配置代码,通过connect将组件和store连接起来
let mapStateToProps = (state) => ({
    userInfo: {...state.redUserInfo}
})

let mapDispatchToProps = (dispatch) => ({})

export default connect(mapStateToProps, mapDispatchToProps)(PageClass)

//通过props获取用户信息
this.props.userInfo

第五步,修改用户信息

import {switchUser} from '../../redux/actions/userInfo'

switchUser({
    userId: 10001,
    userName: '',
    userOpenid: '',
    userPhone: '',
    userRole: 2
})();

至此就完成了redux+React-redux的一个简单使用流程

相关文章:

  • Spring MVC JSP页面加载不完全的问题
  • 工程师笔记|浅析AI平台的架构设计
  • Spark 1.0.0 横空出世 Spark on Yarn 部署(Hadoop 2.4)
  • 使用docker遇到的问题
  • 武汉区块链软件技术公司:区块链将如何优化产业链?
  • echarts简单使用
  • .NET项目中存在多个web.config文件时的加载顺序
  • Linux工具性能调优系列三:swap问题定位
  • Ubuntu 12.04 root账户开启及密码重设
  • ipv6最长前缀匹配算法
  • oracle 11.2.0.1 rman异机恢复 11.2.0.3(windows X64)
  • Linux查询网址
  • GCP为Kubernetes引擎提供支持原生容器的负载均衡器
  • input文本框实现宽度自适应代码实例
  • 牛课练习赛34 Flittle w and Discretization 主席树维护Mex
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • AWS实战 - 利用IAM对S3做访问控制
  • C++入门教程(10):for 语句
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • Codepen 每日精选(2018-3-25)
  • CSS居中完全指南——构建CSS居中决策树
  • eclipse的离线汉化
  • gitlab-ci配置详解(一)
  • JavaScript服务器推送技术之 WebSocket
  • JavaScript函数式编程(一)
  • Linux后台研发超实用命令总结
  • Markdown 语法简单说明
  • Sass Day-01
  • SQLServer之索引简介
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • vue数据传递--我有特殊的实现技巧
  • 检测对象或数组
  • 解决iview多表头动态更改列元素发生的错误
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 为什么要用IPython/Jupyter?
  • 新书推荐|Windows黑客编程技术详解
  • 正则学习笔记
  • 做一名精致的JavaScripter 01:JavaScript简介
  • 第二十章:异步和文件I/O.(二十三)
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​什么是bug?bug的源头在哪里?
  • # 数论-逆元
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (2)nginx 安装、启停
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (SpringBoot)第二章:Spring创建和使用
  • (TOJ2804)Even? Odd?
  • (第27天)Oracle 数据泵转换分区表
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (简单) HDU 2612 Find a way,BFS。
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (三)mysql_MYSQL(三)
  • .cfg\.dat\.mak(持续补充)