• React训练营:状态管理 redux&reactredux


    React概述

    1.Redux是一个用于JavaScript状态容器,提供可预测的状态管理。
    2.Redux可以用于构建一直化的应用,运行于不同的环境,并且易于测试。
    3.Redux除了和React一起使用之外,还支持其他界面库。

    JavaScript需要管理更多的数据:服务器响应、缓存数据、本地生成未持久化的数据,也包括UI状态,如果有一个数据模型Model的变化会引起另外一个Model变化,那么当View变化时,就可能引起对应的model以及另一个model变化,依次可能会引起另外的View变化,导致变量的状态混乱,Redux就是为了解决这样的问题。

    Redux三大核心

    • 单一数据源:整个应用的state被存储在一颗obejct tree中,并且这个object tree只存在于唯一一个store中,保证任何一个页面,拿到State的值都是一致的。
    graph LR state1-->A[object tree] state2-->A[object tree] state3-->A[object tree] state4-->A[object tree] A[object tree]-->Store Store-->A[object tree]
    • State是只读的,唯一改变state的方法就是触发action,action是一个用于描述已经发生的普通对象。
    	store.dispatch([type:'COMPLETE_TODO',index:1])
    
    • 使用纯函数执行修改:为了表述action如何改变state tree,需要编写reducers
    Redux的状态
    Domain State:可以理解为服务端的数据,比如用户的信息,商品的列表
    UI State:决定当前UI展示的状态,弹窗的显示和隐藏,受控组件
    App State:全局的状态,请求是否Loading
    
    Redux的Action

    Action是本质是一个JS对象,把数据从应用传到store的载体,它是store数据的唯一来源,一般来说,可以通过store.dispatch()将action传递给store
    只是描述了事情要发生,并没有描述如何去更新state,在reducer中更新state

    Redux的reducer

    Reduer本质就是一个函数,用来响应发过来的action,然后经过处理,把state发送给Store

    graph LR Componment--store.dispatch-->Reducer---->Store
    Redux的Store

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

    1. 维持应用的state
    2. 提供getState()方法获取state
    3. 提供dispatch()方法发送action
    4. 通过subscribe()来注册监听
    5. 通过subscribe()的返回值来注销监听

    实战

    1.创建组件Button用于发送Action

    import React from "react";
    export default class ReduxDemo extends React.Component{
    	render(){
    		return (
    			<button>点我发送一个Action</button>
    		)
    	}
    }
    

    2.创建Action.js

    export const sendAction = ()=>{
    	//构建Action
    	return {
    		type:"SEND ACTION",
    		value:"发送了一个Action"
    	}
    }
    

    3.创建Reducer.js

    const initState = {value:"默认值"}
    export const reduxDemoReducer = (state=initState,action)=>{
        switch (action.type) {
            case "SEND ACTION":
                return Object.assign({}, state, action);
            default:
                return state;
        }
    }
    

    4.创建Store

    import {createStore} from 'redux';
    import { reduxDemoReducer } from '../redux/reduxDemo/reducers';
    export const store = createStore(reduxDemoReducer);
    

    使用Redux

    给页面的Button按钮绑定一个点击事件
    在组件加载完成的时候通过store来进行监听器的注册,返回值可以用来注销监听

    import React from "react";
    //导入Store
    import { store } from "../../infrastrucure/store";
    //导入action 构建函数
    import { sendAction } from "../../infrastrucure/redux/reduxDemo/actions";
    export default class ReduxDemo extends React.Component{
        handleClick = () =>{
            const action = sendAction();
            //发送一个action
            store.dispatch(action)
        };
        //当组件加载完毕的时候进行监听
        componentDidMount(){
            store.subscribe(()=>{
                console.log("ReduxDemo",store.getState())
                //用于刷新组件的状态
                this.setState({});
            })
        }
        render(){
            return (
                <>
                <button onClick={this.handleClick}>点我发送一个Action</button>
                <div>{JSON.stringify(store.getState())}</div>
                </>
            )
        }
    }
    

    小结

    1. 构建action,通过创建一个函数,然后返回一个对象,注意需要携带type助兴
    2. 构建reducer,用来响应action,然后通过return把数据传回给store
    3. 利用createStore来构建store,构建的时候传递我们写好的reducer
    4. 利用store.subscribe()注册监听
    5. 当我们利用store.dispatch()发送一个action的时候就能触发我们的监听了,在里面利用store.getState()就能拿到值
    graph TD A[Componment]--dispatch-->B[Reducer] B[Reducer]--return-->C[Store] C[Store]--subscribe-->A[Componment]

    React-redux

    如何设置全局Store,避免一直写上述的1~5的步骤?
    React-redux,Redux和React没有关系,Redux支持React、Angular....
    react-redux就是官方出品的用于配合React的绑定库,能够使React组件从Redux store中方便地读取数据,并且向store中分发actions以此来更新数据。
    React-Redux中两个重要的成员:Provider-->能够使得整个App都能获取到store中的数据,connect 能够使得组件和store进行关联。

    Provider、connect

    Provider包裹在根组件最外层,使所有的子组件都能拿到State
    Provider接收store作为props,然后通过context往下传递,这样react中任何组件都可以通过context获取到store

    graph LR A[react-readux Provider]--解决了-->B["容器组件可能存在很深的层级,防止一层一层去传递state"] A[react-readux Provider]--作用-->C["让组件拿到state"] A[react-readux Provider]--原理-->D["react中的context"]

    connect Provider内部组件如果想要使用到state中的数据,就必须要connect进行一层包裹封装,换言之,就必须要被connect加强
    connect 方便我们组件能够获取到store中的state

    参数名 类型 说明
    mapStateToProps(state,ownProps) Function 这个函数允许我们将store中的数据作为props绑定到组件上,state:Redux中的store,ownProps:自己的props
    mapDispatchToProps(dispatch,ownProps) Function 将action作为props绑定我们自己的函数中,dispatch:就是store.dispatch(),ownProps:自己的props
    mergeProps(stateProps,dispatchProps,ownProps Function 不管是stateProps还是dispatchProps,都需要和ownProps merge之后才会被赋给我们的组件,通常情况下,可以不传递这个参数,connect就会使用Object.assign替代该方法
    options Object 可以定制connector的行为

    React-redux,发送数据与接收数据

    1.编写reducer

    
    const initState = {
        count:1
    }
    
    //reducer 要就接收Action,然后进行逻辑处理
    //判断Action是否我们所需要
    //如果是,那么return 一个新的state
    export const plusOne = (state=initState,action)=>{
        console.log('reducer:',action)
        switch (action.type) {
            case 'ADD ACTION':
                return {
                    count: state.count+1
                };
            default:
                return state;
        }
    }
    

    2.消息发送方

    import React from "react";
    //1.导入connect
    import { connect } from "react-redux";
    class PlusOne extends React.Component{
    
        //4.组件中使用
        handlClick=()=>{
            console.log("PlusOne", this.props);
            //发送Action
            this.props.sendAction();
        };
    
    
        render(){
            return (
                <button onClick={this.handlClick}>PlusOne</button>
            );
        }
    }
    
    /**
     * 3.实现connect的第二个参数,用来发送action,这个函数的返回值是一个对象
     * { key: 方法名, value:调用dispatch}
     * @param {*} dispatch 
     */
    const mapDispatchToProps=(dispatch)=>{
        return {
            sendAction:()=>{
                //利用dispatch发送一个action,传递action对象,要定义一个type属性
                dispatch({
                    type:'ADD ACTION'
                })
            }
        }
    };
    
    //PlusOne为消息发送方,2.组件加强
    //connect(要接受数据的函数,要发送action的函数)(放入要加强的组件)
    export default connect(null,mapDispatchToProps)(PlusOne);
    
    

    3.消息接收方

    import React from "react";
    import { connect } from "react-redux";
    class PrintDemo extends React.Component{
        render(){
            console.log("PrintDemo:",this.props)
            return (
                <>
                <div>
                    组件PrintDemo
                </div>
                <div>
                    {this.props.count}
                </div>
                </>
            );
        }
    }
    
    /**
     * 接收两个参数
     * @param {*} state 
     */
    const mapStateToProps=(state)=>{
        console.log("PrintDemo",state)
        return state;
    }
    
    //PrintDemo组件的接收方
    export default connect(mapStateToProps)(PrintDemo);
    

    数据调用流程梳理

    image

  • 相关阅读:
    zabbix4.2.5常见问题指南
    postgres常用运维sql
    centos7部署inotify与rsync实现实时数据同步
    postgres主从基于流复制
    postgres高可用学习篇三:haproxy+keepalived实现postgres负载均衡
    postgres高可用学习篇二:通过pgbouncer连接池工具来管理postgres连接
    postgres高可用学习篇一:如何通过patroni如何管理3个postgres节点
    centos7安装yum安装pip
    nginx1.15.10配置使用非https访问返回403
    zabbix4.2.5自定义告警模板
  • 原文地址:https://www.cnblogs.com/rynerlute/p/16052716.html
Copyright © 2020-2023  润新知