#reactjs #redux #redux-saga #redux-thunk #redux-toolkit
#reactjs #сокращение #redux-сага #сокращение-thunk #redux-toolkit
Вопрос:
Я только начал использовать Redux Toolkit (RTK), и мне трудно найти правильный способ использования createAsyncThunk
из RTK.
Итак, что я пытаюсь сделать, это
- отправка асинхронного действия, созданного
createAsyncThunk
- обновить хранилище с помощью извлеченных данных,
- и отправить другое синхронное действие в рамках того же создателя полезной нагрузки.
Например, вы могли бы написать такой код, 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
снова, причем возвращаемое значение будет обернуто обещанием в качестве полезной нагрузки.
Я мог бы просто использовать обычный боевик или сагу, но причина, по которой я пытаюсь использовать этот способ, заключается в том, чтобы свести к минимуму шаблонность. Использование обычного действия thunk потребует создания создателей действий для ожидающих / успешных / неудачных действий, что не является необходимым при использовании createAsyncThunk
.
Есть ли у кого-нибудь идея, которая могла бы помочь мне решить эту проблему? любые комментарии будут оценены по достоинству. Спасибо вам за чтение.
Ответ №1:
createAsyncThunk
не совсем подходит для этого варианта использования. Он специально предназначен для обработки варианта использования «выборка данных и результат отправки», а не для непрерывной последовательности отправок.
У вас есть доступ к thunkAPI.dispatch
внутренней части обратного вызова создания полезной нагрузки, поэтому вы можете отправлять дополнительные действия до fulfilled
отправки действия. Но 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
действие будет отправлено.
Я думаю, что вашим лучшим вариантом здесь было бы разбить это на два блока: один, который выполняет только обычную выборку отправку исходных данных, и второй блок, который отправляет первый, а затем выполняет дополнительную логику.