Как стать автором
Обновить

bindActionCreators — маленькая утилита, решающая проблемы

Уровень сложностиПростой
Время на прочтение2 мин
Количество просмотров2.4K

В этой статье я хочу поделиться информацией, которая будет полезна всем, кто использует redux или @reduxjs/toolkit

Данные библиотеки предоставляют большое количество полезных утилит, в этой статье я расскажу об одной из них – bindActionCreators

Одна из проблем, преследующая почти всех, кто использует вышеупомянутые библиотеки - невозможность использования action(), предварительно не обернув его в dispatch(). Это порождает большое количество бессмысленного кода:

const dispatch = useDispatch()

const handleReset = (id: number) => dispatch(actionReset(id))

Как использовать bindActionCreators?

Для начала разберемся с аргументами: bindActionCreators(actionCreators, dispatch)

  • actionCreators - объект вида { actionName: ActionDefinition }

  • dispatch - соответственно dispatch из useDispatch() или store

Далее разберем два способа использования по вышеупомянутым методам получения dispatch

Хук useDispatchedActions и useDispatch

const useDispatchedActions = (actionCreators) => {
  const dispatch = useDispatch()

  return bindActionCreators(actionCreators, dispatch)
}

Или в одну строку:

const useDispatchedActions = (actionCreators) => bindActionCreators(actionsCreators, useDispatch())

Также пример этого хук на TypeScript с примером типов

type Store = typeof store
type AppDispatch = typeof Store['dispatch']

type BoundAsyncThunk<Actionы extends ActionCreator<any>> = (
  ...args: Parameters<Action>
) => ReturnType<ReturnType<Action>>

type BoundActions<Actions extends ActionCreatorsMapObject> = {
  [key in keyof Actions]: Actions[key] extends AsyncThunk<any, any, any>
    ? BoundAsyncThunk<Actions[key]>
    : Actions[key]
}

const useDispatchedActions = <Actions extends ActionCreatorsMapObject = ActionCreatorsMapObject> (
  actions: Actions,
): BoundActions<Actions> => {
  const dispatch = useDispatch<AppDispatch>()

  return bindActionCreators(actions, dispatch), [actions, dispatch]
}

Собственная утилита и store.dispatch

const getDispatchedActions = (actionsCreators) => bindActionCreators(actionsCreators, store.dispatch)

Результат же - тот же самый объект, который мы передавали в аргумент с одним отличием - эти экшены мы можем использовать без необходимости оборачивать их вызов в dispatch()

Я бы рекомендовал вам использовать второй метод использования bindActionCreators по двум причинам:

  • Метод более универсален, не принуждает вас использовать его только в других хуках или компонентах

  • Если вы будете использовать хук useDispatchedActions, вам необходимо учитывать, что экшены, которые вы будете получать из хука и использовать в компонентах, eslint будет требовать добавить их в зависимости других React хуков. А это может приводить к неожиданным ошибкам (например к бесконечным вызовам useEffect)

Следующая статья по @reduxjs/toolkit

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии3

Публикации

Истории

Работа

Ближайшие события

One day offer от ВСК
Дата16 – 17 мая
Время09:00 – 18:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область