dea*_*t88 2 redux redux-thunk react-redux redux-toolkit
我试图找出为什么我的异步 thunk 调用没有按预期工作。当我的网站首页加载时,我试图从数据库中提取 JSON 对象数组。现在,API 已被调用,数据已被提取,但动作创建者和切片之间出现了一些问题。我正在尝试console.log action,state但也没有任何结果。
我刚刚学习,redux-toolkit所以对此还很陌生。
这是我的切片:
import { createSlice } from '@reduxjs/toolkit'
const prizesSlice = createSlice({
name: 'prizes',
initialState: {
prizesArray: [],
},
reducers: {
getPrizes(state, action) {
console.log('hello')
state.prizes = action.payload
},
},
})
export const prizesSliceActions = prizesSlice.actions
export default prizesSlice
Run Code Online (Sandbox Code Playgroud)
这是动作创建者:
import { prizesSliceActions } from './prizes-slice'
import { createAsyncThunk } from '@reduxjs/toolkit'
import * as api from '../apiClient'
// get data
export const fetchPrizeData = createAsyncThunk(
'prizesArray/getPrizes',
async () => {
const data = await api.getAllPrizes()
console.log(data)
prizesSliceActions.getPrizes(data)
}
)
Run Code Online (Sandbox Code Playgroud)
以下是它在组件中的调用方式:
import { fetchPrizeData } from '../store/prizes-actions'
[...]
useEffect(() => {
dispatch(fetchPrizeData())
}, [dispatch])
Run Code Online (Sandbox Code Playgroud)
这是我的商店:
import { configureStore } from '@reduxjs/toolkit'
import prizesSlice from './prizes-slice'
const store = configureStore({
reducer: { prizes: prizesSlice.reducer },
})
export default store
Run Code Online (Sandbox Code Playgroud)
好吧,让我试着澄清一下:
主要问题是由“case reducer”函数创建的操作对象getPrizes永远不会被分派到实际的 redux 存储。
听起来势不可挡?让我详细解释一下。
pricesSlice您如何设置切片存在一个问题。
您将初始状态设置为一个对象,该对象具有一个名为 的属性prizesArray,该属性目前使用一个空数组进行初始化。到目前为止一切都很好。
现在您声明了一个名为 的减速器getPrizes,更具体地说是一个“case 减速器” ,它一次性结合了 reduxaction和。reducer
另外,这很好,但是,命名对我来说有点含糊。这是一个“改变”状态的函数,所以它实际上没有
get任何作用,对吧?它真正的作用是setting奖品。所以更合适的名字可能是setPrizes。
好吧,除此之外,现在有一个真正的问题。case 减速器如下所示:
reducers: {
getPrizes(state, action) {
console.log('hello')
state.prizes = action.payload
},
},
Run Code Online (Sandbox Code Playgroud)
您访问state.prizes,但该字段不存在于该状态!记得在initialState名称中设置为prizesArray。因此,正确的函数应该是这样的:
reducers: {
setPrizes(state, action) {
state.prizesArray = action.payload
},
},
Run Code Online (Sandbox Code Playgroud)
或者在初始状态下重命名该字段,由您决定。
现在我们已经修复了,pricesSlice是时候修复其他部分了。
您创建了一个asyncActionThunk,这很好!但是,您随后调用prizesSlice.actions.getPrizes(data),但从未分派此函数创建的操作对象。
我将您的代码转换为打字稿,因此我们实际上可以看到该操作的返回类型:
该函数调用的返回类型只是一个对象。该函数调用只是为您创建一个“redux 操作”对象(或者换句话说,您的减速器函数从未被调用)。现在您需要将该操作对象传递给 redux 以“应用更改”。我们通常dispatch对 redux 进行操作,因此潜在的修复可能如下所示:
export const fetchPrizeData = createAsyncThunk(
"prizesArray/getPrizes",
// - We are getting the thunkApi as second arg.
// On it, we have the dispatch method available to us
async (_, thunkApi) => {
const data = await new Promise((r) => r(["1", "2"]));
// now we dispatch the action object to the redux store
// the state gets updated, yei!
thunkApi.dispatch(prizesSliceActions.setPrizes(data));
}
);
Run Code Online (Sandbox Code Playgroud)
这已经解决了这个问题,因为我们现在dispatch是 redux 的对象。您可以在文档中阅读有关该thunkAPI参数的更多信息。createAsyncThunk
然而,这并不是使用时的最佳方法createAsyncThunk。我们实际上可以完全利用它。我只是按照文档进行操作:
export const fetchPrizeData = createAsyncThunk("prizes/getPrizes", async () => {
const data = await api.getAllPrizes()
console.log(data)
// We just return our data here
return data;
});
const prizesSlice = createSlice({
name: "prizes",
initialState: {
prizesArray: []
},
reducers: {},
extraReducers: (builder) => {
// we setup an extra reducer that will update the state
// when the async thunk resolved
builder.addCase(fetchPrizeData.fulfilled, (state, action) => {
state.prizesArray = action.payload;
});
}
});
Run Code Online (Sandbox Code Playgroud)
这种方法使用得createAsyncThunk更加恰当,因此我们还可以获得在商店上调度更清晰的操作的好处。例如,如果我们使用 redux 开发工具检查分派的操作,我们会发现分派的操作prizes/getPrizes/fullfilled是导致状态更新的操作:
使用另一种方法,我们将在 redux 存储上分派三个操作,并且最好使分派的操作尽可能有意义!
希望这能解决问题,如果还有疑问,请告诉我!
| 归档时间: |
|
| 查看次数: |
1598 次 |
| 最近记录: |