Ответ
Плюсы:
- Простота внедрения — не требует сложных абстракций
- Хорошо подходит для простых асинхронных операций (запросы API)
- Понятный поток данных — действия диспатчатся последовательно
- Минимальный boilerplate по сравнению с Saga
Минусы:
- Сложность тестирования из-за side effects
- Проблемы с композицией асинхронных операций
- Callback hell при сложных цепочках действий
- Нет контроля над отменой операций
// Пример thunk
const fetchUser = (id) => async (dispatch) => {
dispatch({ type: 'FETCH_USER_START' });
try {
const user = await api.getUser(id);
dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
} catch (error) {
dispatch({ type: 'FETCH_USER_ERROR', payload: error });
}
}; Ответ 18+ 🔞
Да ты посмотри, какая хуйня творится с этими thunk'ами! Ну, в рот меня чих-пых, как же их все нахваливают.
Что там у них хорошего, а?
- Впихнуть — не выпихнуть. Серьёзно, проще некуда. Никаких тебе ёбаных генераторов,
yieldи прочей саги — взял и написал функцию, которая возвращает другую функцию. И всё, пиздец, ты уже асинхронный гений. - Для простых дел — огонь. Надо данные с сервака подёргать? Пожалуйста, один
fetch,dispatchдо,dispatchпосле — и в ус не дуешь. - Видно, кто за кем. Действия летят одно за другим, как по маслу. Начало запроса, успех, ошибка — всё на виду, не запутаешься.
- Писанины меньше, чем в той же Saga. Не надо импортировать кучу эффектов, описывать сагу, форкать, вот это всё. Написал колбэк — и свободен.
А теперь, сука, ложка дёгтя, которая блядь целый чан!
- Тестировать — пиздец. Как, блядь, протестировать side effects, которые у тебя прямо в теле функции? Это ж надо мокать весь мир: и
dispatch, иgetState, и API-шку. Овердохуища мороки. - Сложную логику не соберёшь. Ну-ка, попробуй организовать несколько параллельных запросов, которые потом ждут друг друга, или, хуле там, отмену предыдущего. Получится такая вложенная хуйня, что сам через неделю не разберёшь.
- Callback hell, ёпта! Запрос Б зависит от результата А, а потом ещё С нужно сделать... И вот ты уже пишешь
thenвнутриthen, илиasync/awaitна три этажа вглубь. Красота, блядь, смотреть противно. - Отменить? Хуй там! Пользователь ушёл со страницы, а твой thunk уже пошёл делать запрос на десять гигов. Ну и пусть себе грузит, нахуй, память жрёт и трафик. Контроля-то никакого.
// Смотри, как это выглядит на практике. Просто, да?
const fetchUser = (id) => async (dispatch) => {
dispatch({ type: 'FETCH_USER_START' }); // Диспатчим старт
try {
const user = await api.getUser(id); // Ждём, пока сервер не ответит
dispatch({ type: 'FETCH_USER_SUCCESS', payload: user }); // Ура, диспатчим успех
} catch (error) {
dispatch({ type: 'FETCH_USER_ERROR', payload: error }); // Обосрались — диспатчим ошибку
}
};
Короче, инструмент как инструмент. Для быстрого наброса и простых вещей — терпимо. Но как только логика начинает напоминать сценарий фильма про шпионов — всё, пидары, это не ваш выбор. Тут уже надо Saga или RTK Query смотреть, а то совсем охуеете.