React-redux全局状态管理

这篇博客是看一个网上视频的笔记,后面也会根据自己在项目开发过程中遇到的问题进行不断的更新。

目录

Redux概述

什么是Redux

Redux的设计初衷

Redux三大核心

1、单一数据源

2、state是只读的

3、使用存函数来执行修改

Redux组成部分

state状态

action

reducer

 Store

Redux案例

react-redux

Redux概述

什么是Redux

Redux是一个用于Javascript状态容器,可以进行全局状态管理。

Redux可以构建一致化的应用,运行与不同的环境(客户端,服务器,原生应用),并且易于测试。

Redux除了和React一起使用外,还支持其他界面库,而且它体积很小(2KB)。

Redux的设计初衷

随着Javascript单页面开发日益复杂,Javascript需要管理更多的state(状态),这些state可能包括服务器响应、缓存数据、本地生成未持久化到服务器的数据,也包括UI状态等。

管理不断变化的state非常麻烦,如果一个model的变化会引起另外model的变化,那么当view发生变化时,就可能引起对应model以及另一个model的变化,依次可能引起其他view的变化,所以逻辑处理就会比较混乱。而Redux就为了解决这个问题的。Redux可以进行全局状态管理。

Redux三大核心

1、单一数据源

整个应用的state都被保存在一个object tree中,Object Tree只存在于唯一的一个store中。

React-redux全局状态管理_第1张图片

2、state是只读的

说state是只读的,并不意味着state不能修改。

如果修改state需要触发一个action。action是一个用于描述已发生事件的普通对象。

这样确保了视图和网络请求都不能直接去修改state。它们只能表达想要修改的意图。所有的修改都会被集中化处理,并且按照一个接一个的顺序执行。

3、使用存函数来执行修改

为了描述action如何改变state,需要编写reducers。

reducers是一些纯函数,它接收先前的state和action,并且返回新的state。

可以复用、控制顺序、传入附加参数。

Redux组成部分

state状态

state就是我们传递的数据。state可以分为三类:

(1)DomainDate:从服务器请求到的数据

(2)UI state:控制UI展示的状态,比如弹框的显示隐藏等

(3)App state:App级别的状态,比如路由信息可以被多个组件使用到的状态

action

action是把数据从应用传到store载体,它是store数据的唯一来源,可以通过store.dispatch()将action传递给store

reducer

reducer本质就是一个函数,可以响应发送过来的action,经过处理,将state发送给store。

注意:在reducer函数中,需要return返回值,这样store才能接收到数据。

函数会接收两个参数,第一个参数是初始化state,第二个是action

React-redux全局状态管理_第2张图片

 Store

store就是把action与reducer联系到一起的对象。

store维持应用的state状态,提供getState()方法获取state,提供dispatch()方法发送action,通过subscribe()注册监听,通过subscribe()返回值注销监听

redux的工作流程

React-redux全局状态管理_第3张图片 

 组件component通过action载体向store中发送数据,store通过reducers将新的state存到store中,其他组件就可以从store中拿到新的state状态。

类似于去图书馆借书的流程

React-redux全局状态管理_第4张图片

 

Redux案例

构建项目之后,安装redux,安装命令:

npm i redux

在scr文件夹下创建action文件夹,并在action文件夹下创建index.js文件。在index.js中通过创建一个函数,返回一个aciton对象,其中action对象中必须要有type属性。

/**
 * action 构建函数
 */
export const sendAction = () => {
    // 需要返回一个action对象,该action对象需要包括type等属性
    return {
        type: 'send-action',
        value: '这是一个action'
    }

}

接着在src文件夹下创建reducer文件夹,在reducer文件夹中创建index.js文件。在index.js文件中处理action,通过return将数据传给store.

/**
 * 该文件是创建reducer函数,专门用于处理发送过来的action
 */

const initState = {
    value: '默认值'
}
// 函数需要传递两个参数:state,action
const rootReducer = (state = initState, action) => {
    console.log('reducer:', state, action)
    // 根据aciton中的type字段判断是否为发送过来的action,如果是则返回一个新的state
    switch (action.type) {
        case 'send-action':
            return Object.assign({}, state, action)
        default:
            return state
    }
}
export default rootReducer;

接着利用createStore来构建store,createStore方法中传入reducer。

import { createStore } from 'redux'
import { rootReducer } from '../reducer';
const store = createStore(rootReducer)

export default store;

在Home组件中通过store.subscribe()注册监听,当利用store.dispatch()发送action时就会触发监听,然后就可以通过store.getState()方法获取数据

import React from "react";
// 引入store
import store from '../../store'
// 引入action构建函数
import {sendAction} from '../../action'

export default class Home extends React.Component {
    constructor(props) {
        super(props)
    }

    sendAction() {
        // 通过sendAction创建一个action
        const action = sendAction()
        // 发送一个action
        store.dispatch(action)
    }

    componentDidMount() {
        // 注册监听
        this.unsubscribe = store.subscribe(() => {
            // 通过getState()方法获取state
            console.log('subscribe: ', store.getState())
            // 获取到监听之后,可以通过this.setState()方法触发页面重新渲染
            this.setState({})
        })
    }
    componentWillUnmount() {
        // 取消监听
        this.unsubscribe()
    }
    render() {
        return (
            

store获取的值:{store.getState().value}

) } }

结果:

未点击发送action之前:

点击发送aciton之后:

React-redux全局状态管理_第5张图片

上面的示例,我们会发现每创建一个store,我们就需要导入该store,并且要注册/取消监听,比较麻烦,react-redux为我们解决了这个问题。

react-redux

第一步:安装依赖:

npm install redux

npm install react-redux

第二步:按redux的示例创建action、reducer、store等方法,然后创建两个组件,并引入到app.js中。

第三步:引入Provider

在app.js中引入react-redux库中的Provider组件,用Provider组件包裹项目结构,并给Provider设置store属性,传入我们创建的store。这样Provider就可以统一维护store了。

import CompA from "./page/CompA";
import CompB from "./page/CompB";
import store from '../src/store'

// 导入Povider组件,利用这个组件包裹项目结构,从而统一维护store
import { Provider } from "react-redux";


function App() {
  return (
    // 为Provider传入store
    
      
); } export default App;

第三步:使用react-redux库中的connect

Provider只是维护store,真正使用store还需要connect。connect可以把组件和store进行关联。

connect的使用方法的简单介绍:

使用方法:connect(...)(组件) 

ps:connect(...)返回的是一个方法,所以才能继续跟(组件)

connect(...)的参数说明:

React-redux全局状态管理_第6张图片

具体详情可以查看react-redux官方文档对connect的讲解

 其中mapStateToProps和mapDispatchToProps比较重要。

mapStateToProps: (state, ownProps?) => Object,哪个组件需要接收store的数据,就实现该方法,如果不想订阅store更新可以传入null或者undefined代替mapStateToProps

mapDispatchToProps?: Object | (dispatch, ownProps?) => Object,哪个组件需要发送store数据,就实现该方法。

发送方CompA

import React from "react";
// 导入connect方法
import { connect } from "react-redux";
class CompA extends React.Component {

    addCount() {
        console.log('CompA: ', this.props)//由日志可以发现sendAction会被传过来
        // 所以我们就可以利用sendAction发送数据
        this.props.sendAction()
    }
    render() {
        return (
            
CompA组件:
) } } //创建mapDispatchToProps方法-使用箭头函数实现,最后action会被作为一个props传递给组件 const mapDispatchToProps = (dispatch) => { // 需要返回一个对象 return { // 对象使用key-value的形式。另外根据对redux使用可以知道sendAction也是一个方法实现 sendAction: () => { // 利用dispatch发送一个action dispatch({ // action必须要有type属性 type: 'add-action' }) } } } /* CompA是数据发送方,所以要实现connect的第二个参数mapDispatchToProps */ export default connect(null, mapDispatchToProps)(CompA)

接收方CompB

import React from "react";
// 导入connect方法
import { connect } from "react-redux";

class CompB extends React.Component {
    render() {
        return (
            
CompB组件接收到的数据:{this.props.count}
) } } const mapStateToProps = (state) => { // 在这里必须要return state return state } // 接收方 export default connect(mapStateToProps, null)(CompB)

reducer:

const initState = {
    count: 0
}
export const rootReducer = (state = initState, action) => {
    console.log('reducer:', state, action)
    switch (action.type) {
        case 'add-action':
            // 在reducer中返回了新的state,才能触发相关的接收组件获取新的数据
            return {
                count: state.count + 1
            }
        default:
            return state
    }
}

store

import { createStore } from 'redux'
import { rootReducer } from '../reducer';
const store = createStore(rootReducer)

export default store;

数据传递流程

React-redux全局状态管理_第7张图片

你可能感兴趣的:(React,react.js,前端,reactjs,redux,状态管理)