2022/4/11

6-4 使用Redux-thunk 中间件实现ajax数据请求
第一步,安装: yarn add redux-thunk
第二步,在store/index.js中引入applyMiddleware:

import { createStore, applyMiddleware, compose } from 'redux';

applyMiddleware使我们可以使用中间件
第三步,引入thunk,在store/index.js中引入:

import thunk from 'redux-thunk';

第四步,将thunk注册到applyMiddleware中,使thunk成为store的中间件(因为applyMiddleware属于redux)

(注意:redux在创建store的时候才能用中间件,thunk是redux的中间件
除了thunk,调错工具某种意义上来讲也是中间件
第五步,因为中间件有两个,通过redux的compose可以实现注册两个或以上中间件,这也是redux注册中间件的高级写法。
代码:

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

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
  applyMiddleware(thunk),
);

const store = createStore(reducer, enhancer);

export default store;

这里,enhancer就是两个中间件。原先应是 applyMiddleware([thunk,window.__REDUX_DEVTOOLS_EXTENSION_.....])

react–>jsx编译。只有import React from ‘react’ 才能用jsx语法。(不管是无状态组件函数也是一样的)

关于thunk:
1、不使用中间件,store接收的action只能是对象;有了中间件(redux-thunk),action可以是一个函数,通过store.dispatch这个方法将action函数传给store。
2、store接收到action之后发现action是函数而不是对象,则会执行调用这个action函数。
3、action函数内部先进行异步请求获取数据,之后去改变store中的数据(state)。
4、首先内部创建一个action对象,外部action这个函数默认接收store的dispatch方法,因此直接调用dispatch方法将内部action对象传给store,store便可以更新数据。

以上,已经完成了关于redux-thunk的注册了。接下来就是看怎么用。
redux-thunk的作用就是将异步操作移到action那里去。
原本,action是个对象,因为thunk,action可以作为一个函数。

代码,看getTodoList怎么写的:
store/actionCreator.js中(专门写action的地方)

import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, INIT_LIST_ACTION } from './actionTypes';
import axios from 'axios';

export const getInputChangeAction = (value) => ({
	type: CHANGE_INPUT_VALUE,
	value
});

export const getAddItemAction = () => ({
	type: ADD_TODO_ITEM
});

export const getDeleteItemAction = (index) => ({
	type: DELETE_TODO_ITEM,
	index
});

export const initListAction = (data) => ({
	type: INIT_LIST_ACTION,
	data
});

export const getTodoList = () => {
	return (dispatch) => {
		axios.get('/list.json').then((res) => {
			const data = res.data;
			const action = initListAction(data);
			dispatch(action);
		})
	}
}

在组件中是:

    import { getTodoList, getInputChangeAction, getAddItemAction, getDeleteItemAction } from './store/actionCreators'

componentDidMount() {
const action = getTodoList();
store.dispatch(action);
}

这里:getTodoList是函数。是特殊的action。
store.dispatch(action),当action是函数时,执行这条语句会自动执行。
该action函数可以接收到store的dispatch。
所以就是

(dispatch) = > {
   axios.get('./list.json').then((res)=>{
       const data = res.data
       const action  = initListAction(data)
       dispatch(action)
}
}

看了一下别人解释的thunk,所谓thunk,中间件,它就是在action和store之间,也就是dispatch,thunk是对dispatch
的封装。当传入dispatch是函数时,它允许函数先执行,等到函数里面执行了dispatch(对象),即dispatch(action),action
时对象时,再调用store去管理action

dispatch会根据参数的不同,执行不同的事情。

redux还有其它中间件,比如redux-logger,可以记录action每次派发的日志。

解决redux异步的中间件除了redux-thunk,还有redux-saga

redux的所有中间件指的都是action和store的中间。

使用redux-saga中间件:redux-saga跟redux-thunk一样,都是实现将异步操作放在action。
第一步:yarn add saga
第二步:store/index.js:

import { createStore, applyMiddleware, compose } from 'redux';
import reducer from './reducer';
import createSagaMiddleware from 'redux-saga';
import todoSagas from './sagas';

const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware));

const store = createStore(reducer, enhancer);
sagaMiddleware.run(todoSagas);

export default store;

第三步,由于saga将异步的逻辑放在单独的文件里,因此创建store/sagas.js,就是上面那个todoSagas,
这个中间件除了在createStore创建后,还需要使用sagaMiddleware.run(todoSagas);语句。
TodoSagas是一个generator函数。
saga可以捕获action。(通过takeEvery)

function* mySaga() {
  yield takeEvery(GET_INIT_LIST, getInitList);
}

mySaga通过捕捉action.type===GET_INIT_LIST的action,在它进入store之前先执行getinitList函数。
getinitList函数里面可以写很多代码,比如可以写异步相关代码。

整体mySaga代码如下:(store/sagas.js)

import { takeEvery, put } from 'redux-saga/effects';
import { GET_INIT_LIST } from './actionTypes';
import { initListAction } from './actionCreators';
import axios from 'axios';

function* getInitList() {
	try {
		const res = yield axios.get('/list.json');
		const action = initListAction(res.data);
		yield put(action);
	}catch(e) {
		console.log('list.json网络请求失败');
	}
}

// generator 函数
function* mySaga() {
  yield takeEvery(GET_INIT_LIST, getInitList);
}

export default mySaga;

注意:1.因为sagas.js里没有store,所以无法store.dispatch(action),只能 put(action)
2.在generator函数里,异步函数不用promise,用yield即可,代码:const res = yield axios.get('/list.json');
yield证明会等待,会等待获得res再执行下面的语句。
3.yield put(action);(generator函数的专属写法,跟store.dispatch(action)一个意思,这里action是对象)
4.因为yield axios.get(‘/list.json’);代替了promise,但这样没有then或catch,如果出错了就会出现问题,所以需要用到try…catch

redux-thunk适合简单项目,比起redux-saga,没有太多api,只是action既可以是对象,也可以是函数。
thunk允许函数在执行到dispatch(action)后,再将action派发给store.

今天在学打包,呃,其实好像很简单,主要是部署交给测试做了,但我觉得迟早有一天需要我去做,找个时间学一下吧!
两个打包,打包后压缩dist目录,把dist压缩包发给测试。一共有两个,
npm run build:prod,这是仿真环境。
npm run build:stage,这是测试环境

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值