react整合原生redux(二)

前言

react整合原生redux(一)已经完成了一个基本的应用框架,但是在分发action的时候,并不能在action里写逻辑,换言之action始终只是json对象,不能是一个函数,虽然可以在视图生命周期内写逻辑方法改变state的数值,但是长此以往,会造成项目臃肿,维护困难,所以react-thunk中间件由此而生

项目创建

参考 react整合原生redux(一)

增加依赖包

yarn add redux-thunk -s

src文件目录

|-app.js
|-store.js
|-index.js
|-actions.js

多了一个actions.js文件,里面存放带逻辑的action

action.js内容

// actions.js
/**
 * redux-thunk action格式为一个函数,返回值是使用了dispatch的函数
 * 基本格式
 * function () {
 *  return function (dispatch) {
 *    dispatch(...)
 *  }
 * }
 */
export const fetchListAction = param => {
  return dispatch => {
    // 模拟异步请求请求数据(fetch,axios等)
    new Promise(resolve => {
      setTimeout(() => {
        const data = {
          code: 0,
          msg: "ok",
          data: {
            list: ["hello", "thunk"],
            param
          }
        };
        resolve(data);
      }, 2000);
    }).then(result => {
      dispatch({ type: "SAVE", payload: result.data });
    });
  };
};

store改动

引入redux-thunk

完整代码

// store.js
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension"; //chrome redux调试工具

// state初始值
const initState = {
  list: ["a", "b"]
};

// reducer格式
const reducer = (state = initState, action) => {
  const { type, payload } = action;
  // action的type处理
  if (type === "SAVE") {
    return Object.assign({}, state, payload);
  }
  return state;
};

/**
 * 实例化store
 * 参数1: reducer
 * 参数2: 中间件
 */
export default createStore(
  reducer,
  composeWithDevTools(applyMiddleware(thunk))
);

在app.js中调用

主要是这段

useEffect(() => {
    store.dispatch(fetchListAction({ id: 1 }));
}, []);

完整代码

// app.js
import React, { useState, useEffect } from "react";
import store from "./store";
import { fetchListAction } from "./actions";

export default () => {
  // 获取store中的state,并放进hook函数,类似this.setState(store.getState())
  const [state, setState] = useState(store.getState());
  useEffect(() => {
    // store订阅函数,当state通过store.dispatch分发action改变时此函数自动执行
    store.subscribe(() => {
      setState(store.getState()); //重新设置组件state的值,使视图更新
    });
  }, []); // []表示只执行一次

  // 模拟首次载入页面请求数据
  useEffect(() => {
    store.dispatch(fetchListAction({ id: 1 }));
  }, []);

  const { list } = state;

  const addList = () => {
    list.push(Date.now());
    store.dispatch({ type: "SAVE", payload: { list } }); //分发一个 action 对象
  };

  return (
    <div>
      <button onClick={addList}>add</button>
      <ul>
        {list.map(v => {
          return <li key={v}>{v}</li>;
        })}
      </ul>
    </div>
  );
};

这样就可以应付一般中小型项目的需求了,查看完整代码

一般大型项目用redux-saga,请看react整合原生redux(三)


zpfei
186 声望7 粉丝

往事如风~