redux-thunk,redux-saga的使用

1. redux-thunk

// store/index.js

import { createStore, applyMiddleware, compose } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";

const sagaMiddleWare = createSagaMiddleWare(); 

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // 这个是redux devtools

// applyMiddleware使用中间件
const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(thunk))
);

export default store;
// store/reducer.js

import { combineReducers } from "redux";

import { countReducer } from "./count";

import { asyncReducer } from "./async";

// reducer的拆分
const reducer = combineReducers({
  countInfo: countReducer,
  asyncInfo: asyncReducer,
});

// combineReducers的原理如下,combineReducers多做了state的优化,如果没有改变就返回原来的,不会像下面一直返回的是新的{}
// reducer最后是一个函数,函数的返回值是一个对象
// function reducer(state={},action) {
//   return {
//     countInfo: countReducer(state.countInfo,action),
//     asyncInfo: asyncReducer(state.asyncInfo,action)
//   }
// }

export default reducer;
// store/async/index.js

import asyncReducer from "./reducer";
import * as asyncAction from "./action";
import * as asyncConst from "./constant";

export { asyncReducer, asyncAction, asyncConst };


// store/async/constant.js


export const BANNER= "BANNER";

export const RECOMMEND= "RECOMMEND";

export const SAGADATA= "SAGADATA";


// store/async/action.js

import { BANNER, RECOMMEND, SAGADATA } from "./constant";
import { asyncFn } from "@/api";


export const getBanner = (banner) => ({ type: BANNER, banner });

export const getRecommend = (recommend) => ({ type: RECOMMEND, recommend });


// redux-thunk的使用
// 原理就是传入的action是个函数,判断typeof如果是function就进行拦截
// 拦截后执行这个函数,并将dispatch和store.getState当做参数传入
export const getAsyncData = (dispatch, getState) => {
  asyncFn.getMulti().then((res) => {
    const data = res.data.data;
    dispatch(getBanner(data.banner.list));
    dispatch(getRecommend(data.recommend.list));
  });
};

export const getSagaData = () => ({ type: SAGADATA, name: "666" });

// store/async/reducer.js

import { BANNER, RECOMMEND } from "./constant";

const asyncInfo = {
  banner: [],
  recommend: [],
};

// reducer是纯函数 结合state和action,返回新的state
function changeCounter(state = asyncInfo, action) {
  switch (action.type) {
    case BANNER:
      return { ...state, banner: action.banner };
    case RECOMMEND:
      return { ...state, recommend: action.recommend };
    default:
      return state;
  }
}

export default changeCounter;



// redux-thunk的使用页面

import React, { Component } from "react";
import { connect } from "react-redux";
import { asyncAction } from "./store/async";

export class TThunk extends Component {
  componentDidMount() {
    this.props.getData();
  }

  render() {
    const { banner, recommend } = this.props;
    return (
      <div>
        <hr />
        <h4>redux-thunk的使用</h4>
        <ul>
          {banner.map((ban) => (
            <li key={ban.acm}>{ban.title}</li>
          ))}
        </ul>
        <hr />
        <ul>
          {recommend.map((red) => (
            <li key={red.acm}>{red.title}</li>
          ))}
        </ul>
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  banner: state.asyncInfo.banner,
  recommend: state.asyncInfo.recommend,
});

const mapDispatchToProps = (dispatch) => ({
  getData() {
    dispatch(asyncAction.getAsyncData);
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(TThunk);

2. generator的使用

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 生成器函数
      function* test() {
        console.log(1);
        const r1 = yield "hello";
        console.log(r1);
        const r2 = yield "world";
        console.log(r2);
        const r3 = yield "666";
        console.log(r3);
      }

      // 迭代器
      const it = test(); //执行生成器,会返回迭代器,不会执行里面的内容
      const it1 = it.next(); // 使用一次next,就消耗一次迭代器
      console.log(it1);
      const it2 = it.next("返回值"); //传入参数,会作为返回值
      console.log(it2);
      const it3 = it.next();
      console.log(it3);
      const it4 = it.next();
      console.log(it4);

      // generator和promise的使用
      function* getData() {
        const res = yield new Promise((resolve) => {
          setTimeout(() => {
            resolve("hello promise");
          }, 2000);
        });
        console.log(res);
      }

      const itp = getData();
      // itp.next()返回的是Promise,然后执行到2s后,执行最后一个next,把值传进去,作为参数,会返回给res
      itp.next().value.then((msg) => {
        itp.next(msg);
      }); // 执行结果:hello promise
    </script>
  </body>
</html>

3. redux-saga的使用

// store/index.js

import { createStore, applyMiddleware, compose } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";
import saga from "./saga"; // 业务saga的generator汇总
import createSagaMiddleWare from "redux-saga";

const sagaMiddleWare = createSagaMiddleWare(); 

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // 这个是redux devtools

// applyMiddleware使用中间件
const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(sagaMiddleWare, thunk))
);

sagaMiddleWare.run(saga); // saga运行,监听哪些action generator

export default store;
// store/saga.js

import { all, takeLatest, call, put } from "redux-saga/effects";
import { asyncAction, asyncConst } from "./async";
import { asyncFn } from "../../api";

function* getMultiData(action) { 

  // 这里判断是否是Promise,然后it.next().value.then((res)=>{it.next(res)}); 这样返回值就能获取到 
  const res = yield call(asyncFn.getMulti, { name: action.name });
  const dt = res.data.data;
  // 多个处理方式
  yield all([
    put(asyncAction.getBanner(dt.banner.list)),
    put(asyncAction.getRecommend(dt.recommend.list)),
  ]);
}

// 监听action generator,每次dispatch(SAGADATA)会进行拦截,执行getMultiData generator
function* watchData() {
  // 多个SAGADATA一起执行时候,takeLatest会拦截最后一个,takeEvery则是每个都执行
  yield takeLatest(asyncConst.SAGADATA, getMultiData);
}

export default function* rootSaga() {
  // 多个处理方式  
  yield all([watchData()]);
}
// redux-saga的使用页面

import React, { Component } from "react";
import { connect } from "react-redux";
import { asyncAction } from "./store/async";

export class TSaga extends Component {
  componentDidMount() {
    this.props.getData();
  }

  render() {
    const { banner, recommend } = this.props;
    return (
      <div>
        <hr />
        <h4>redux-saga的使用</h4>
        <ul>
          {banner.map((ban) => (
            <li key={ban.acm}>{ban.title}</li>
          ))}
        </ul>
        <hr />
        <ul>
          {recommend.map((red) => (
            <li key={red.acm}>{red.title}</li>
          ))}
        </ul>
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  banner: state.asyncInfo.banner,
  recommend: state.asyncInfo.recommend,
});

const mapDispatchToProps = (dispatch) => ({
  getData() {
    dispatch(asyncAction.getSagaData());
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(TSaga);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值