一篇搞定React状态管理Redux&React-redux使用详解(保姆级教程!!!)

如果React只是入门的同学,或者对Redux这个状态管理库不是很了解的朋友,这篇文章应该会对你有些帮助。

一、组件间传值方案(组件间通信)

了解 React 的朋友应该都知道React是状态数据驱动的框架。React组件组件之间传值有很多种情况,但是组件之间传值只有通过props,context,回调函数 来实现(不借助外部类库)。

  • 父组件传值给自组件 ( props属性 )
  • 自组件传值给父组件 ( 回调函数 )
  • 兄弟组件传值 (需要传递的值传给 共有的父组件,然后兄弟组件通过props从父组件获取传递值)

上面是一些最常用的情况,但是如果在大型项目中,组件嵌套四五层层甚至更多,这时候有个需求说把第4层的一个值传给另一个关系甚远的堂兄组件,怎么搞?如果一层层的向上传值找到公共的祖先组件然后再通过props一层层的传?

这个时候如果有一个仓库能够帮我们管理这些状态,组件直接的修改值,获取值直接通过这个仓库来统一管理,再也不用像上面一层层的传值,是不是很爽?

二、状态集中管理仓库 Redux

一篇搞定React状态管理Redux&React-redux使用详解(保姆级教程!!!)_第1张图片
根据redux的工作流程画了个简单的流程图。接下来我们根据流程图来说下redux数据流是怎么流转的。

  • store 数据仓库
  • reducer 仓库管理员
  • action 修改数据的信号
  • view component 项目所有的组件
1.工作流程

首先我们需要创建一个仓库store,仓库里面可以存放组件们需要的数据state

store仓库创建需要招聘处理外部动作信号的仓库管理员reducer

reducer 管理员由 store 直接管理,reducer 管理员通过action 动作传递的信号的type来做相应的提前预定好的动作来管理store中的数据。

action 信号由数据用户view component 来触发,通过store 提供的联系方式 store.dispatch() 来发送action

view component 可以通过store.getState()来获取仓库的所有数据,从而来提取自己需要的数据。
如果view component 希望store中的数据有改动的时候就通知自己,那么就需要订阅subscribe 仓库store,也就是在仓库的通知列表里面填一下联系方式,当仓库数据修改的时候,仓库会给订阅过的view comonent发送最新的数据。

2.代码实践

接下来我将写代码模拟父母挣钱,孩子索要零花钱来改变家庭资金的过程。
一篇搞定React状态管理Redux&React-redux使用详解(保姆级教程!!!)_第2张图片

  1. 创建React项目(create-react-app)
    create-react-app redux-demo 
    //脚手架安装 npm install -g create-react-app 
  1. 创建store文件夹
    一篇搞定React状态管理Redux&React-redux使用详解(保姆级教程!!!)_第3张图片
  2. 初始化 store 仓库
//store.js
import { createStore} from 'redux';
import reducer from './reducer'

//初始化工厂数据 state
const initState = { money: 0 };

//创建store工厂
const store = createStore(
    reducer,
    initState,
);

export default store;
  1. store初始化需要reducer管理员
//reducer.js
//仓库管理员,接受action发送的信号,处理返回结果数据
const reducer = (state = {}, action) => {
    let newState;
    switch (action.type) {
        case 'SAVA_MONEY'://挣钱
            newState = Object.assign({}, state);
            newState.money += action.payload
            return newState;
        case "OUT_MONEY"://取钱
            newState = Object.assign({}, state);
            newState.money -= action.payload
            return newState;
    }
    return state;
}
export default reducer;
  1. 组件获取仓库中的数据state
//Family.jsx
import React, { Component } from 'react';
import store from './store/store';
import { saveMoney, outMoney } from './store/action'

class Couple extends Component {

    constructor(props) {
        super(props);
        this.state = store.getState()
        store.subscribe(() => {
            let newState = store.getState();
            //重新触发render,从而通过store.getState()获取到新值
            this.setState(newState);
        })
    }

    render() {
        const { money } = this.state;
        return (
            <div>
                <p>Family Money:{money}</p>
                Couple:
                <button onClick={() => {
                    const saveMoneyAction = saveMoney(100)
                    store.dispatch(saveMoneyAction)
                }}>赚钱</button>
                <hr />
                {this.props.children}
            </div>
        );
    }
}

class Child extends Component {

    componentDidMount() {
        store.subscribe(() => {
            this.setState({})
        })
    }

    render() {
        const state = store.getState();
        return (
            <div>
                <p>Family Money: {state.money}</p>
                Child:
                <button onClick={() => {
                    const say = outMoney(20)
                    store.dispatch(say)
                }}>索要零花钱</button>
            </div>
        )
    }
}


export { Couple, Child };
//action.js
export const saveMoney = (money) => {
    return {
        type: 'SAVA_MONEY',
        payload: money
    }
}

export const outMoney = (money) => {
    return {
        type: 'OUT_MONEY',
        payload: money
    }
}

三、react-redux

按照上面redux的使用流程,每个组件都需要通过store.getState获取state值,而且都需要订阅等等,真正项目中如果直接这么使用会代码冗余,不方便维护。

通过react-redux可以很好的简化上面的过程。

import React, { Component } from 'react';
import { saveMoney, outMoney } from './store/action';
import { connect } from 'react-redux'

class Couple extends Component {

    constructor(props) {
        super(props);
        this.state = {}
    }

    render() {
        const { money, saveMoney } = this.props;
        debugger
        return (
            <div>
                <p>Family Money:{money}</p>
                Couple:
                <button onClick={() => {
                    const saveMoneyAction = saveMoney(100)
                }}>赚钱</button>
                <hr />
                {this.props.children}
            </div>
        );
    }
}

class Child extends Component {


    render() {
        const { money, outMoney } = this.props;
        return (
            <div>
                <p>Family Money: {money}</p>
                Child:
                <button onClick={() => {
                    const say = outMoney(20)
                }}>索要零花钱</button>
            </div>
        )
    }
}
//将store中的state数据映射到组件的props中
const mpStateToProps = (state) => {
    debugger
    return {
        money: state.money
    }
}

//将store中方法映射到组件到props中
const mpDisptchToProps = (dispatch) => {
    return {
        saveMoney: (money) => { dispatch(saveMoney(money)) },
        outMoney: (money) => { dispatch(outMoney(money)) }
    }
}

const MyCouple = connect(mpStateToProps, mpDisptchToProps)(Couple);
const MyChild = connect(mpStateToProps, mpDisptchToProps)(Child);

export {
    MyCouple,
    MyChild
};

项目入口 index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import { MyCouple, MyChild } from './Family'
import store from './store/store'

const App =
  <Provider store={store}>
    <MyCouple>
      <MyChild />
      <MyChild />
    </MyCouple>
  </Provider>

ReactDOM.render(
  App,
  document.getElementById('root')
);

四、 Redux DevTools 插件

Chrome浏览器插件方便开发追溯redux状态的扭转记录。
一篇搞定React状态管理Redux&React-redux使用详解(保姆级教程!!!)_第4张图片

//创建store工厂
const store = createStore(
    reducer,
    initState,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
);

附加redux的三大原则(加深理解redux的好处和对付面试 ^ _ ^)
(1)单一数据源:整个应用的state被存储在一棵object tree中,并且这个object tree只存在于唯一一个store中;
(2)state是只读的:唯一改变state的方法就是触发action,action是一个用于描述发生事件的普通对象;
(3)使用纯函数修改数据;

你可能感兴趣的:(#,React,进阶之路,前端知识图谱,redux,react状态管理)