企业级 Redux 应该怎么用--部署篇

本篇文章参考以下博文

  • 说一说React和Redux你知道或者不知道的一些事情
  • kolodny/immutability-helper

    文章目录

      • 前言
      • 一、顶层 Redux
        • 1.1 configureStore
        • 1.2 顶层 reducer
        • 1.3 middleware
      • 二、组件中的 Redux
        • 2.1 数据上传
        • 2.2 数据使用

前言

  上一节总结了一下项目结构,相信大家有了一个初步的认识,还没有看的小伙伴戳这里–结构篇,本篇文章,我们结合代码细节,来一起部署一下 redux

一、顶层 Redux

  顶层 redux 的项目如下,我们挨个看每个文件的配置。
企业级 Redux 应该怎么用--部署篇_第1张图片

1.1 configureStore

  首先,先看三个 configureStore 文件,最中间的 configureStore.js 细节如下:

if (precess.env.NODE_ENV === "production") {
  module.exports = require("./configureStore.prod");
} else {
  module.exports = require("./configureStore.dev");
}

  没看错, configureStore.js 这个文件里面只有这 5 行代码,这里有的同学会有一个问题,这个 precess 是什么,没有引入,直接使用会不会报错?这个变量是 node 提供给我们的环境变量,用来获取当前是属于开发环境还是生产环境,只要安装了 node 的计算机,都是可以识别的,另外 react 的运行环境也需要提前安装 node 所有同学们不用担心会不会报错的问题。

  下面是关于两个环境的对比图 ,可以看出开发环境比生产环境多了一个热模块替换的功能。
企业级 Redux 应该怎么用--部署篇_第2张图片

  多的这部分功能,是为了在更新 reducer 的时候不用去重启服务,达到修改直接生效的目的。

  还有一处需要理解的地方

applyMiddleware(thunkMiddleware, api)

  这一部分代码是使用包含自定义功能的 middleware 来扩展 redux Middleware 可以让你包装 store dispatch 方法来达到你想要的目的,每个 middleware 都不需要关心链中它前后的 middleware 的任何信息。类似于设计模式中的装饰器模式。

1.2 顶层 reducer

  顶层中的 reducer 里面,不会去配置具体业务,而是整合整个模块里面的各个小的 reducer ,具体代码如下:

import { combineReducers } from "redux";
import DemoItemReducer from "../DemoItem/Components/DataQuery/redux/reducers";

const rootReducer = combineReducers({
  DemoItemReducer
});
export default rootReducer;

  可以看出,上面代码显示引入了一个联合方法,然后引入我们写的各个组件的 reducer ,整合后导出。

1.3 middleware

  这个文件夹里面就包含了我们对于 store dispatch 方法的包装。 api.js 文件的具体配置如下。

export default ({ dispatch, getState }) => next => action => {
  const { types, axiosAPI, callback } = action;
  if (!types) {
    return next(action);
  }
  if (
    !Array.isArray(types) ||
    types.length !== 3 ||
    !types.every(type => typeof type === "string")
  ) {
    throw new Error("EXpected an arrat of three string types.");
  }
  if (typeof axiosAPI !== "function") {
    throw new Error("EXpected axiosAPI to be a function.");
  }
  if (typeof callback !== "object") {
    throw new Error("EXpected callback to be a object.");
  }
  const [starType, successType, failureType] = types;
  const {
    messageSuccess = () => {},
    messageFailed = () => {},
    callbackFunc = () => {},
    dataProcessing = () => {}
  } = callback;

  dispatch({
    type: starType
  });
  return axiosAPI()
    .then(response => {
      if (response.data.ErrCode !== 200) {
        if (response.data.ErrCode !== 1010) {
          return;
        }

        dispatch({
          type: failureType,
          errorMsg: response.data.ErrCode || "failed"
        });
        messageFailed();
      } else if (response.data.ErrCode === 200) {
        dispatch({
          type: successType,
          data: dataProcessing(response.data.data) || response.data.data
        });
        messageSuccess();
        callbackFunc(dispatch, response.data.data);
      }
    })
    .catch(error => console.log(error));
};

  上面的配置主要是针对接口调用中一些类型的校验和接口返回值的异常的处理。

二、组件中的 Redux

  下面是一个组件中的层级结构。
企业级 Redux 应该怎么用--部署篇_第3张图片

2.1 数据上传

   DataQuery.js 组件里面当需要使用 redux 的时候,会先触发一个 action ,然后 action 会去找对应的 reducer reducer 收到请求后,会把数据存入到 store 中,这样就完成了一次数据上传。

  界面使用 redux 的时候,格式如下:

import SaveLaneLineInfo from './redux/action';
...
let { dispatch } = this.props;
dispatch(SaveLaneLineInfo(data)) //调用action,传入需要更新的数据

   action 文件中的配置如下:

export const LANE_LINE_INFO = "LANE_LINE_INFO"; //线条信息

//保存线条信息
export function SaveLaneLineInfo(laneLineInfo) {  //此方法为上面组件中调用的方法
  return {
    type: LANE_LINE_INFO,
    laneLineInfo
  };
}

  上面调用 action 后会去执行 reducer 中的方法

import update from "react-addons-update";
import { combineReducers } from "redux";
import {
  LANE_LINE_INFO, //线条信息
} from "./action";

const DEFAULT_DATA_LINE = {
  showLaneData: {
    Id: 123,
    width: "小芳",
    number: 18
  }
};

function setLineInfo(state = DEFAULT_DATA_LANE, { type, payload }) {  //需要给state一个初始值,防止异常情况时,state的值出现错误
  switch (type) {
    case LANE_LINE_INFO: {
      return update(state, {
        showDetailData: {
          Id: {
            $set: payload.Id
          },
          width: {
            $set: payload.width
          },
          number: {
            $set: payload.number
          }
        }
      });
    }
    default: {
      return state;
    }
  }
}

const rootReducer = combineReducers({
  setLineInfo,
});

export default rootReducer;

  到这里,就完成了数据上传,我们更新的数据已经存入到 store 里面了。

2.2 数据使用

  接下来一个问题,如何去使用 store 里面的数据,好多同学对于这里的理解不是很清楚,只是模模糊糊的会用,但具体不知道为什么。

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

class DataQuery extends Component {
  ...
}

function mapStateToProps(state) {  // ***
  let { showDetailData } = state.setLineInfo;
  return {
    showDetailData
  }
}

export default connect(mapStateToProps)(DataQuery)  //***

  重点在于观察 mapStateToProps 函数 和 最下面 导出的格式发生了改变。 connect redux 提供的一个可以在组件加载的时候同时去执行其他任务的增强函数,上面导出的含义是当导出 DataQuery 组件的时候,同时执行一下 mapStateToProps 方法,该方法会连接 state props ,然后返回我们需要使用的 store 中的值。

  这一大段有点绕,需要反复琢磨几遍。

let { showDetailData } = state.setLineInfo;
  return {
    showDetailData
  }

  上面这部分代码, setLineInfo reducer 中的导出的方法名, showDetailData 是导出这个方法的时候,设置的属性名。
企业级 Redux 应该怎么用--部署篇_第4张图片
   上面蓝色框中的 $set redux update 的固定格式,表示设置 Id 属性值为 payload 中的 Id

  配置完以上内容后,我们的 redux 才算真正的部署完成,接下来你就可以在配置好的组件里面随意使用了,只需要通过以下方式,就可以获取到值了。

this.porps.showDetailData // showDetailData为mapStateToProps函数中返回的值

  以上便是对于 实际开发中, redux 如何部署的总结,欢迎各位大佬指点不足之处,可能由于是文字介绍,不如视频形象,有些地方也讲解的比较模糊,有疑问的同学欢迎私信我,共同探讨。




你可能感兴趣的:(React配套,reactjs)