createAsyncThunk:在同一个有效负载创建者内,用提取的数据更新存储后,调度更多操作



我刚开始使用Redux Toolkit(RTK(,我很难从RTK中找到使用createAsyncThunk的正确方法。

所以我想做的是

  1. 调度createAsyncThunk创建的异步操作
  2. 使用提取的数据更新存储,
  3. ,并在同一有效负载创建者内调度另一个同步操作


例如,您可以使用redux-saga编写这样的代码,如下所示。

function* fetchBooksSaga() {
try {
yield put(fetchBooksStart()); // set loading
const keyword = yield select(state => state.keyword); // get keyword from store
const { data } = yield call(SearchBooksAPI, query); // fetch books
yield put(fetchBooksSuccess(data)); // set books

// Here, you can dispatch another action with newly updated state.
const books = yield select(state => state.books);
// I know you can just use 'data' variable here,
// but let's say you have to update store first.
yield put(anotherAction(books)); 
} catch (error) {
yield put(fetchBooksFailure(error)); // set error
}
}

我试图用createAsyncThunk编写相同的代码,结果如下所示。

export const fetchBooks = createAsyncThunk(
'BOOKS/FETCH_BOOKS',
async (params, ThunkAPI) => {
try {
// when 'fetchBooks' is dispatched, fetchBooks.pending will be dispatched automatically.
const { keyword } = ThunkAPI.getState(); // get keyword from store.
const { data } = await SearchBooksAPI(query); // fetch books
ThunkAPI.dispatch(fetchBooks.fulfilled(data)); // set books

// store updated at this moment
const { books } = ThunkAPI.getState();
ThunkAPI.dispatch(anotherAction(books));

// NOPE - returning value here will dispatch fetchBooks.fulfilled again.
return data;
} catch (error) {
ThunkAPI.rejectWithValue(error); // dispatch fetchBooks.rejected
}
}
);

和它的名称一样,有效负载创建者应该创建一个有效负载。所以很明显,我应该在有效负载创建者中返回一些东西。但在这种情况下,返回值将再次调度asyncAction.fulfilled,返回值由Promise包装作为有效载荷。

我可以用一个普通的重击动作或传奇故事,但我尝试这种方式的原因是尽量减少样板。使用正常的thunk操作将需要为挂起/成功/失败创建操作创建者,而在使用createAsyncThunk时这是不必要的。

有人能帮我解决这个问题吗?如有任何意见,我们将不胜感激。感谢您的阅读。

createAsyncThunk并不完全适用于该用例。它是专门用来处理";获取数据和调度结果";用例,而不是正在进行的调度序列。

确实可以在有效负载创建回调中访问thunkAPI.dispatch,因此您可以在调度fulfilled操作之前调度其他操作。但是,在返回的promise解析之前,fulfilled操作不会被调度,因此它不能让您在完成后调度更多的操作。

我现在能想到的最接近的事情是这样的:

export const fetchBooks = createAsyncThunk(
'BOOKS/FETCH_BOOKS',
async (params, ThunkAPI) => {
try {
// when 'fetchBooks' is dispatched, fetchBooks.pending will be dispatched automatically.
const { keyword } = ThunkAPI.getState(); // get keyword from store.
const { data } = await SearchBooksAPI(query); // fetch books

const resultPromise = Promise.resolve(data);

resultPromise.then(() => {
const { books } = ThunkAPI.getState();
ThunkAPI.dispatch(anotherAction(books));
})

return resultPromise;
} catch (error) {
ThunkAPI.rejectWithValue(error); // dispatch fetchBooks.rejected
}
}
);

但我不确定这个承诺何时得到解决以及fulfilled操作何时被调度的时机是否完全正确。

我认为你最好的选择是把它分成两个thunk:一个只对原始数据进行正常的fetch+调度,另一个thunck调度第一个,然后进行额外的逻辑。

最新更新