React学习:redux中间件

1 篇文章 0 订阅
1 篇文章 0 订阅

为什么redux需要中间件?因为我们redux中有很多数据需要异步请求,所以需要中间件帮助我们在redux中完成异步请求。

1.redux-thunk中间件

1.1安装
yarn add redux-thunk

1.2 在store中使用

import { createStore, applyMiddleware } from 'redux'; // 导入应用中间件这个方法
import reducer from './reducer';
import thunkMiddleware from 'redux-thunk'; // 导入redux-thunk

const enhance = applyMiddleware(thunkMiddleware); // 生成一个enhancer

const store = createStore(reducer, enhance); // createStore中,可以传入第二个参数,enhancer
export default store;

1.3定义一个返回函数的action和另一个action
// 中间件在调用这个函数后,会传入dispatch和getState这两个参数,都是方法来的
export function getData() {
  return (dispatch, getState) => {
    axios
      .get('https://api.apiopen.top/getJoke?page=1&count=2&type=video')
      .then((res) => {
        dispatch(get(res));
      });
  };
}
export function get(data) {
  return {
    type: types.GET,
    data,
  };
}
1.4 在页面上使用
import React, { PureComponent } from 'react';
import { getData } from './store/actionCreators';
import { connect } from 'react-redux';
class App extends PureComponent {
  render() {
    return (
      <div>
      {/*点击按钮发送异步请求*/}
        <button onClick={(e) => this.props.getList()}>获取数据</button>
      </div>
    );
  }
}
const mapStateToProps = (state) => ({
 
});
const mapDispatchToProps = (dispatch) => ({
  getList: () => {
    dispatch(getData()); // 在这里dispatch我们那个返回函数的action,记得调用getData
  },
});
export default connect(mapStateToProps, mapDispatchToProps)(App);

1.5 在reducer中配置我们的get那个action
case types.GET:
      console.log(action.data);
      return { ...state, list: action.data };

redux-thunk的具体实现:redux-thunk在内部中,重写了dispatch方法,可以让dispatch方法可以接收一个函数作为参数,并将真正的dispatch和getState这个两个方法传给了那个函数。例如:

const store = {}
store.dispatch = () => {
	console.log('dispatch')
}
const tem = store.dispatch
function newDispatch() {
	console.log('加工')
	tem()
	console.log('加工')
}
store.dispatch = newDispatch
store.dispatch()

//输出: 加工 dispatch 加工

2.redux-saga中间件

2.1安装
yarn add redux-saga
2.2在store中配置并使用
import { createStore, applyMiddleware } from 'redux';
import reducer from './reducer';

// 2.redux-saga的配置:
import createSagaMiddleware from 'redux-saga'; // 导入创建saga中间件的方法
import saga from './saga'; // 导入我们自己编写的saga.js

const sagaMiddleware = createSagaMiddleware(); // 调用以下创建saga的方法,生成saga中间件
const enhancer = applyMiddleware(sagaMiddleware); // 应用中间件

const store = createStore(reducer, enhancer); // 在创建store的时候传enhancer进去

sagaMiddleware.run(saga); // run以下saga
export default store;

2.3创建两个action,一个是触发saga的action,另一个是修改store的action
// 触发saga的媒介,你有多少个要修改store的action,就有多少个这样触发saga的媒介action
export function saga() {
  return {
    type: 'SAGA',
  };
}
export function changeDataBySaga(data) {
  return {
    type: 'CHANGE_DATA',
    data,
  };
}
2.4创建并编写saga.js文件
// 在redux-saga/effects中,可以导出我们需要的takeLatest,put,all,takeEvery方法
import { takeLatest, put, all,takeEvery } from 'redux-saga/effects';
// 导入我们需要的修改Store的action
import { getDataBySaga } from './actionCreators';
import axios from 'axios';

// 捕获到action的处理函数
function* getdata() {
	// 利用yield的特性,可以获取到异步的结果
  const res = yield axios.get(
    'https://api.apiopen.top/getJoke?page=1&count=2&type=video'
  );
  // 使用put方法dispatch我们的action
  yield put(changeDataBySaga(res));
  // 如果有多个put,我们可以使用all这个函数:
  // yield all([
  	//put(changeDataBySaga(res)),
  	//put(changeDataBySaga1(res1))
  ])
}

// 创建generator函数,并将这个函数导出
function* mySaga() {
  yield takeLatest(SAGA, getdata);
  // yield takeEvery('SAGA', getdata);
  // yield all([
		//takeEvery('SAGA',getdata),
		//takeLatest('SAGA1',getdata1),
		//takeLatest('SAGA2',getdata2)
	])
  // 我们这里是takeLatest是用来捕获action的type为SAGA的,如果捕获到就交给getdata这个generator进行处理
  // takeLatest和takeEvery的区别:当我们短时间内,触发多次action,takeLatest只捕获最后一次,而takeEvery每次都捕获。
  // all方法的使用:可以让你少写yield这个单词,你将你所需要捕获的takeEvery或者takeLatest放进数组中,并传给all方法,他就会自动帮你调用了
}
export default mySaga;

解释说明:function*和yield是es6中的generator语法,生成器函数,不懂的可以去百度了解一下。

2.5在页面中使用
import React, { PureComponent } from 'react';
import {  saga } from './store/actionCreators';
import { connect } from 'react-redux';
class App extends PureComponent {
  render() {
    return (
      <div>
        <button onClick={(e) => this.props.getListBySaga()}>
          获取数据BySaga
        </button>
      </div>
    );
  }
}
const mapStateToProps = (state) => ({
  
});
const mapDispatchToProps = (dispatch) => ({
  getListBySaga: () => {
    dispatch(saga()); // dispatch我们那个action媒介,让saga可以捕获
  },
});
export default connect(mapStateToProps, mapDispatchToProps)(App);

redux-saga的实现思路:有点像设计模式中的监听者和观察者的模式,saga监听着是否有需要进行异步操作的action进行dispatch,如果有,就进行对应的异步操作,再通过dispatch另一个action来修改我们store中的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值