Thunk Flashcards
CreateAsyncThunk
Как выглядело раньше:
const createTodo = (title) => (dispatch, getState) => {async…;dispatch(…)}
Как в RTK
const createTodo = createAsyncThunk(
‘@@todos/create-todo’, async (title, { dispatch, getState, extra}) => {
dispatch(addLoading());
const res = await fetch(‘http://…)
const data = await res.json();
dispatch(addTodo(data));
}
);
@@todos/create-todo - action
async - асинхронная функция которая и представляет собой санк;
title - title параметр который мы передаем как раньше;
{} - а обьект это thunkAPI в котором находятся наши функции;
И уже в приложении dispatch(createTodo )
ExtraReducer
В созданном Thunk-e createTodo есть ключи (actions):
- pending - в ожидании;
- rejected - ошибка в запросе;
- fullfilled - все хорошо;
которые мы можем использовать в extraReducere.
extraReducer: (builder) => {
builder.addCase(createTodo.pending)
Масавая обработка ExtraReducer (методы в builder in ExtraReducer)
Когда у нас логики работы Thunk-ов много и мы хотим обрабатывать похожим образом
например обрабатывать ошибки и статусы загрузки у нас может произайти некое дублирование.
В ExtraReducer у нас есть 3 метода:
1. addCase - который мы использували ранее;
2. addDefaultCase - подходит больше для аналитики, считать количество екшинов, что произошло;
3. addMatcher - проверяет значение(pending, reject или еще что-то) и делает логику.
пример. (пишится после .addCase())
.addMatcher( (action) => action.type.endsWith(‘/pending’), (state, action) => {
state.loading = ‘loading’;
state.error = null;
}
Функция называется предикатором
RejectWithValue
Метод обработки ошибки который возвращается из объекта thunk там где dispatch and getState
Отмена запроса
Можем проверить не работет ли запрос в данный момент, а можем отменить запрос если юзер покинул страницу.
если осуществляется второй запрос когда первый не выполнился:
export const createTodo = createAsyncThunk(
‘@@todos/create-todo’,
async (title) => {
const res = await fetch(‘http://localhost:3001/todos’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify({ title, completed: false }),
});
const data = await res.json();
return data; }, { condition: (title, { getState, extra }) => { const { loading } = getState().todos; if (loading === 'loading') { return false; } }, } );
отмена запроса когда юзер закрыл страницу.
Мы можем сделать в нашем UI в useEffect() - в момент размонтирование.
useEffect(() => { const promise = dispatch(loadTodos()); return () => { promise.abort(); }; }, [dispatch]);
Екстра прараметры
Если мы хотим добавить экстра параметр то нама нужно прописать мидлвеер в момент создания стора.
export const store = configureStore({
reducer: {
todos: todoReducer,
filter: filterReducer,
},
devTools: true,
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
thunk: {
extraArgument: api
}
})
});
В api все наши запросы (пример ниже).
export const createTodo = async (title) => {
const res = await fetch(BASE_URL, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’
},
body: JSON.stringify({title, completed: false})
})
const data = await res.json();
return data; }
В СЛАЙСАХ МЫ ПИШЕМ
export const createTodo = createAsyncThunk(
‘@@todos/create-todo’,
async (title, {extra: api}) => {
return api.createTodo(title)
}
);
Где в UI мы диспатчем этот action