React 配置 Redux

Redux 

  Redux是 JavaScript 应用程序的可预测状态容器。

  随着项目代码的不断丰富,项目中状态和业务逻辑分散在每个模块里。这让组件的重复使用变得更加困难,也让组件的数量越来越臃肿。Redux 会尝试拆分 程序数据业务逻辑,将它们放在 React 自己的容器中,这样 React 就可以专注于对 视图的管理 了。这让你的软件变得更灵活。

  Redux的优缺点:

    优缺点并不全面

     优势:

       1、数据流流动很自然,因为任何 dispatch 都会导致广播,需要依据对象引用是否变化来控制更新粒度。

       2、如果充分利用时间回溯的特征,可以增强业务的可预测性与错误定位能力。

    缺点:

      1、action和reducer太繁琐。一套或者几套action和reducer的组合,看起来很不错,但是一旦功能和需求多了,action和reducer就会很混乱,如果管理不善,都不能愉悦的写代码了。

      2、store和state的模棱两可。没有严格的定义哪些存store,哪些存internal state。

      3、dispatch是同步的,而且dispatch没办法确认action是否执行成功。

   并不是所有情况下 Redux 都是明智的选择,应用 Redux 的场景:

     * 你有着相当大量的、随时间变化的数据

     * 你的 state 需要有一个单一可靠数据来源

     * 你觉得把所有 state 放在最顶层组件中已经无法满足需要了

  

  一、安装

    更目录下运行命令安装 redux

npm install --save redux

    安装 react-redux

npm install --save react-redux

    安装 react-logger

npm install --save redux-logger

  

  二、编辑代码

    1、React 项目

      代码框架主要延用的是上一节 webpack4+react 配置出来的项目代码。

      项目github: https://github.com/Lyh97/wenpack4-react

    

    2、action

     Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch()将 action 传到 store。

      (1)src下创建 constants 文件夹,其中创建 actionType.js 文件

        我们约定,action 内必须使用一个 字符串类型type 字段来表示将要执行的动作。多数情况下,type 会被定义成 字符串常量。当应用规模越来越大时,建议使用 单独的模块或文件 来存放 action。因此我们定义一个文件来专门存放 actiontype常量

        actionType.js

export const HELLO_SET = 'HELLO_SET';

      (2) src 下创建 action 文件夹,其中创建 index.jshello.js

        Action创建函数 就是生成 action 的方法。“action”“action 创建函数” 这两个概念很容易混在一起,使用时最好注意区分。在 Redux 中的 action创建函数 只是简单的返回一个 action :

        hello.js

import * as actionTypes from '../constants/actionTypes';

export function setHello(hello) {
  return {
    type: actionTypes.HELLO_SET,
    hello
  };
};

        index.js

import { setHello } from './hello';

export {
  setHello
};

       

    3、Reducers

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

      在 src 下创建 reducers 文件夹,其中创建 hello.js 以及 index.js。

        hello.js

import * as actionTypes from '../constants/actionTypes';

const initialState = [];

export default function(state = initialState, action) {
  switch (action.type) {
    case actionTypes.NAME_SET:
      return setHello(state, action);
  }
  return state;
}

function setHello(state, action) {
  const { hello } = action;
  return [ ...state, ...hello ];
}

        index.js

import { combineReducers } from 'redux';
import name from './hello';

export default combineReducers({
  hello
});

    4、Stores     

      action 来描述“发生了什么”, reducers 来根据 action 更新 state 的用法。

      Store 就是把它们联系到一起的对象。强调一下 Redux 应用只有一个单一的 store。     

      Store 有以下职责:

      

      src 下创建 stores 文件夹,其中创建 configureStore.js

        configureStore.js

import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers/index';
import { createLogger } from 'redux-logger';

const logger = createLogger();

const createStoreWithMiddleware = applyMiddleware(logger)(createStore);

export default function configureStore(initialState) {
  return createStoreWithMiddleware(rootReducer, initialState);
}

    

    5、组件中的使用

      src/index.js也需要编辑:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import AppTest from './App';
import * as serviceWorker from './serviceWorker';

import configureStore from './stores/configureStore';
import * as actions from './actions';
import { Provider } from 'react-redux';

const hello = 'Hello Word !!';

const store = configureStore();
store.dispatch(actions.setName(hello));

ReactDOM.render(
    <Provider store={store}>
        <AppTest />
    </Provider>, 
    document.getElementById('root'));
serviceWorker.unregister();

      我将 redux 用在了我的 App.jsx 组件里 我在其中通过 {this.props.hello} 应用了 redux 中的变量 ,我的 App.jsx 是这么写的。

import React from 'react';
import { connect } from 'react-redux';

class AppTest extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 2
        }
    }
    render() {
        return (
            <div>
                <p>{this.state.a}</p>
                {this.props.hello}
            </div>
        )
    }
}

function mapStateToProps(state) {
    return {
      hello : state.hello
    }
}
export default connect(mapStateToProps)(AppTest);