Redux工具包:Async Thunk无法正确连接到我的Reducer

vlju58qv  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(167)

我试图弄清楚为什么我的异步thunk调用没有像预期的那样工作。当我的网站的首页加载时,我试图从我的数据库中取出一个JSON对象数组。现在api被击中了,数据被取出,但是在操作创建者和切片之间有东西福尔斯了。我试图console.logactionstate,但是什么也没有出现。
我只是在学习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

下面是行动创造者:

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)
  }
)

下面是在teh组件中调用它的方式:

import { fetchPrizeData } from '../store/prizes-actions'
[...]
  useEffect(() => {
    dispatch(fetchPrizeData())
  }, [dispatch])

这里是我的店:

import { configureStore } from '@reduxjs/toolkit'

import prizesSlice from './prizes-slice'

const store = configureStore({
  reducer: { prizes: prizesSlice.reducer },
})

export default store
798qvoo8

798qvoo81#

好吧,让我试着澄清一下:
主要问题
主要的问题是,由“case reducer”函数getPrizes创建的操作对象永远不会被调度到实际的redux存储。
听起来很让人难以招架?让我详细解释一下。
这是一个
设置切片的方式有一个问题。
将初始状态设置为一个对象,该对象具有一个名为prizesArray的属性,该属性目前用一个空数组初始化。
现在您声明了一个名为getPrizes的reducer,更具体地说是一个“case reducer”,它将redux actionreducer组合在一起。
当然,这也没什么,但是,我觉得这个名字有点含糊。这是一个“改变”状态的函数,所以它实际上并没有什么作用,对吧?它真正做的是setting奖励。所以更合适的名字应该是setPrizes
好吧,先不说这个,现在有个真实的的问题。减速器看起来像这样:

reducers: {
  getPrizes(state, action) {
    console.log('hello')
    state.prizes = action.payload
  },
},

你访问了state.prizes,但是这个字段在状态中不存在!记住在initialState中,名称被设置为prizesArray。所以正确的函数应该是这样的:

reducers: {
  setPrizes(state, action) {
    state.prizesArray = action.payload
  },
},

或者在初始状态下重命名字段,由您决定。
既然我们已经修复了pricesSlice,现在是时候修复其他部分了。

异步操作形实转换

您创建了一个asyncActionThunk,这很好!但是,您随后调用了prizesSlice.actions.getPrizes(data),但您从未调度此函数创建的操作对象。
我把你的代码转换成了typescript,所以我们可以看到该操作的返回类型:

函数调用的返回类型 * 只是一个对象 *。函数调用只不过是为你创建了一个“redux action”对象(或者换句话说,你的reducer函数还没有被调用)。现在由你来决定是否将action对象传递给redux以“应用更改”。我们通常将dispatch action对象传递给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));
  }
);

这已经解决了这个问题,因为我们现在将对象dispatch redux。你可以在这里的文档中阅读更多关于createAsyncThunk中的thunkAPI参数的信息。

**但是,**这不是使用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;
    });
  }
});

这种方法可以更好地使用createAsyncThunk,这样我们也可以得到更清晰的存储操作。例如,如果我们用redux dev工具检查已调度的操作,我们会看到已调度的操作prizes/getPrizes/fullfilled是导致状态更新的操作:

使用另一种方法,我们将在redux存储上分派三个操作,并且最好使分派的操作尽可能有意义!
希望这澄清了它,如果有问题离开,只是让我知道!

相关问题