Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Thunk и зачем он нужен
Thunk — это функция, которая откладывает вычисление или выполнение кода до момента, когда он действительно понадобится. В контексте Redux и асинхронного программирования на JavaScript, Thunk решает важную проблему: как отправить асинхронные действия в store.
Проблема, которую решает Thunk
Redux по умолчанию работает только с синхронными действиями (actions). Если нужно выполнить асинхронную операцию (HTTP запрос, чтение файла, таймер), то обычный action dispatch не поможет:
// Это не работает с Redux
const fetchUser = (id) => {
const response = await fetch(`/api/users/${id}`);
return {
type: 'FETCH_USER_SUCCESS',
payload: response.json(),
};
};
dispatch(fetchUser(1)); // Ошибка: не можем await
Решение: Redux Thunk Middleware
Redux Thunk — это middleware, который позволяет dispatch-ить не просто actions, а функции (thunks). Функция-thunk получает dispatch и getState как аргументы и может выполнять асинхронный код:
import { createAsyncThunk } from '@reduxjs/toolkit';
// Создаём async thunk
const fetchUser = createAsyncThunk(
'users/fetchUser',
async (id, { rejectWithValue }) => {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error('Network error');
return await response.json();
} catch (error) {
return rejectWithValue(error.message);
}
}
);
// В компоненте
import { useDispatch, useSelector } from 'react-redux';
function UserProfile({ userId }) {
const dispatch = useDispatch();
const { data, loading, error } = useSelector(state => state.users);
useEffect(() => {
dispatch(fetchUser(userId));
}, [userId, dispatch]);
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
return <div>{data.name}</div>;
}
Как работает Thunk
- Диспатч функции — вместо объекта-action отправляем функцию
- Middleware перехватывает — Redux Thunk перехватывает функцию
- Выполняет код — middleware вызывает функцию с
dispatchиgetState - Отправляет actions — внутри функции можем вызвать
dispatchнесколько раз:
// Старый стиль (без Redux Toolkit)
const fetchUserThunk = (id) => async (dispatch, getState) => {
dispatch({ type: 'FETCH_USER_START' });
try {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
dispatch({
type: 'FETCH_USER_SUCCESS',
payload: data,
});
} catch (error) {
dispatch({
type: 'FETCH_USER_ERROR',
payload: error.message,
});
}
};
dispatch(fetchUserThunk(1)); // Работает!
Redux Toolkit (современный подход)
Redux Toolkit упрощает работу с thunks через createAsyncThunk:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
interface User {
id: number;
name: string;
email: string;
}
interface UsersState {
data: User | null;
loading: boolean;
error: string | null;
}
const fetchUser = createAsyncThunk<User, number>(
'users/fetchUser',
async (id, { rejectWithValue }) => {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
return rejectWithValue('Failed to fetch user');
}
return response.json();
}
);
const usersSlice = createSlice({
name: 'users',
initialState: { data: null, loading: false, error: null } as UsersState,
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(fetchUser.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
});
},
});
export default usersSlice.reducer;
Альтернативы Thunk
- Redux Saga — более мощная, для сложной асинхронной логики
- Redux Observable — для асинхронного управления потоками событий
- TanStack Query — специально для работы с серверными данными (рекомендуется вместо Redux для запросов)
Когда использовать Thunk
- Асинхронные HTTP запросы (fetch, axios)
- Работа с сетью и таймерами
- Сложная асинхронная логика приложения
- Когда нужен доступ к
getStateдля проверки текущего состояния
Резюме
Thunk — это функция, которая откладывает вычисления и позволяет Redux работать с асинхронным кодом. Redux Toolkit предоставляет удобный API через createAsyncThunk, который автоматически генерирует pending/fulfilled/rejected actions. Для простых запросов к серверу рекомендуется использовать TanStack Query вместо Redux.