create-react-app的redux范例,createAsyncThunk与addcase
发布于 作者:苏南大叔 来源:程序如此灵动~redux
中对于异步函数的处理,是使用createAsyncThunk
定义的。苏南大叔也说了,要是想修改state
,还是需要在slice
里面做个reducer
接应,里应外合才能修改数据。上一篇文章中,苏南大叔是使用dispatch
来执行内应函数的。实际上,redux
官方推荐里面,并不是用这种方式来对接的,而是定义了钩子函数,对异步的状态进行监控。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔的代码故事。本文描述slice
内的addCase
的概念,看看redux
是如何通过addCase
勾住异步请求的三个状态的。测试环境:win10
,node@16.14.2
,create-react-app@5.0.1
,reduxjs/toolkit@1.8.3
,react-redux@8.0.2
,chrome@103.0.5060.53
,redux-devtools-extension@3.0.11
。
官方范例定义
在上一篇文章中,苏南大叔对这个createAsyncThunk
相关逻辑进行了魔改。具体参考:
本文中将把魔改的部分回滚一些,
- 增加了
slice
内的extraReducers
的builder.addCase()
部分。 createAsyncThunk
中没有使用dispatch
,而是使用了return
。fetchCount
内中,增加了reject()
的调用。
原理上是这样的:
addCase
实际上就是钩子的挂载点,它根据action
定义或者action.type
进行区分。- 异步操作,会产生三种状态。三种状态的区分,是通过修改
type
来进行区分的。
addCase
核心代码中,通过builder.addCase()
这个链式调用,来添加三种状态的state
处理方式。
- 短暂的必然存在的状态就是
.pending
,这个比较好理解。 - 大多数时候,都是处理请求成功状态
.fulfilled
的,返回值通过action.payload
来体现。 - 个别时候,是处理异常请求状态
.rejected
的,其中的message
是可以自定义的。
注意:createAsyncThunk()需要适时的return
,而不是dispatch()
。
export const c = createSlice({
//...
extraReducers: (builder) => {
builder
.addCase(incrementAsync.pending, (state) => {
state.status = 'loading';
})
.addCase(incrementAsync.fulfilled, (state, action) => {
state.status = 'idle';
state.value += action.payload;
})
.addCase(incrementAsync.rejected, (state, action) => {
state.status = 'reject';
state.error = action.error.message;
});
},
});
因为addCase()
的第一个参数,可以表述为函数本身,也可以表述为字符串。所以,当对同一个asyncThunkAction
添加钩子的时候,会报错。比如:"counter/fetchCount/pending"和“incrementAsync.pending”实际上一个效果,会报错。
值得特殊说明的是:addCase()
可以添加三种状态的钩子。但是,不能添加普通无状态的钩子。对于asyncThunkAction
来说,下面的钩子是用于不会执行的。但是,如果是普通的action
,确是可以执行的。
.addCase(action_type, (state) => {
//...
})
createAsyncThunk
因为有上一篇文章的讲解,这里就着重说以下几点。如果发生异常的话,
- 通过
reject(err.message)
来触发的。 - 如果没有定义钩子的话,这里
createAsyncThunk()
里面就需要一个try()catch(e){}
。 - 如果定义了钩子,就不需要
try()catch(e){}
了,会自动转到.rejected
流程,并且接收action.error.message
。
export function fetchCount(amount = 1) {
return new Promise((resolve, reject) =>{
const axios = require('axios');
axios.get("http://127.0.0.1:3222/hello?n="+amount).then(res => {
resolve({ data: res.data });
})
.catch(err => {
reject(err.message);
});
});
}
export const incrementAsync = createAsyncThunk(
'counter/fetchCount',
async (amount,action) => {
const response = await fetchCount(amount);
// action.dispatch(incrementByAmount(response.data));
return response.data;
}
);
注意,这个地方是return
,而不是dispatch
。
相关文章
- https://newsn.net/say/create-react-app-redux.html
- https://newsn.net/say/redux-slice.html
- https://newsn.net/say/redux-useselector.html
- https://newsn.net/say/redux-usedispatch.html
- https://newsn.net/say/redux-createasyncthunk.html
- https://redux.js.org/tutorials/essentials/part-5-async-logic#reducers-and-loading-actions
综述
对于create-react-app
的redux
模版来说,到本文为止,主要的核心内容都讲完了。但是redux
的其它内容,还有很多没有讲述。这些将会在后续文章里面补充。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。