Задать вопрос

Зачем нужен redux-thunk?

Сегодня с коллегой возникла небольшая дискуссия, я утверждал, что redux-thunk очень удобная надстройка (middleware) над redux и позволяет создавать асинхронные экшены.
Коллега возразил, зачем нужен redux-thunk, когда можно сделать вот так:
export function load(){
    setTimeout(()=>{
        store.dispatch(getProfileSuccess({id: 1}));
    }, 3000)
}

Т.е он импортит store в определенный файл проекта и вызывает несколько экшенов

По началу я впал в ступор, действительно, зачем redux-thunk, если можно испортить стор, но позже проанализировав ситуацию, пришел к выводу, что асинхронные экшены, например как в примере выше загрузка профиля должна иметь 3 состояния:
- старт загрузки профиля (для отображения лоадера)
- данные профиля успешно загружены
- возникла ошибка при загрузке данных
исходя из этого, если действовать по методу коллеги, необходимо создавать для каждого действия отдельную функцию (экшены)

Вот пример с использованием redux-thunk
export function getProfile () => {
  return dispatch => {
    // диспатчим лоадер
    dispatch({
      type: GET_PROFILE_START,
      payload: true
    })
    
    axios.get('/user')
      .then(res => {
        // успешно получили данные
        dispatch({
          type: GET_PROFILE_SECCUESS
          payload: res.data
        })
      })
      .cath(err => {
        // Ошибка...
        dispatch({
          type: GET_PROFILE_ERROR
          payload: true
        })
      })
  }
}


Преимущества redux-thunk очевидны, и больше всего мне нравится то, что с помощью redux-thunk всю логику можно хранить в экшенах и тем самым разгрузить компоненты, это одновременно делает проект чище, ведь логика будет находится внутри экшенов, вместо того, чтобы импортить стор в разные части проекта

Что вы скажите, какое мнение верно, и имеет ли права на жизнь предложенное коллегой решение?
  • Вопрос задан
  • 21152 просмотра
Подписаться 3 Оценить Комментировать
Решение пользователя Максим К ответам на вопрос (5)
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Если я правильно понял вашего коллегу, то речь была не о том, что нужно асинхронные функции через setTimeout вызывать, а это был просто пример, как сделать какой-то кусочек "типа асинхронным".
Его довод был в том, что вместо вызова dispatch из замыкания (полученного с помощью redux-thunk, например) он вызывал store.dispatch напрямую (то есть у объекта store, и этот store импортировал бы в каждом файле).

В таком случае, у redux-thunk - одно преимущество явное - не нужно импортировать store в каждом файле.

В остальном, все очень четко расписано в ответе Дэна Абрамова, который привел holymotion.
Если быть кратким, то вам нужна функция dispatch, ведь именно через нее вы "диспатчите" свои экшены. Вы не можете в асинхронном ответе написать:
...
axios.get('/user')
      .then(res => {
        // успешно получили данные
        dispatch({ // <-- здесь вы вызываете функцию dispatch, а если она к вам не пришла в анонимной функции, с помощью redux-thunk, то октуда вы ее возьмете?
          type: GET_PROFILE_SECCUESS
          payload: res.data
        })
      })
...


Поэтому вы были бы обязаны в каждый action creator, который является асинхронным, передавать бы помимо нужных вам аргументов, еще и функцию dispatch из своего контейнера. Что не удобно. (это все есть по ссылке на stackoverflow, но более подробно)
Ответ написан