В этой статье я хочу поделиться информацией, которая будет полезна всем, кто использует 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
)
Комментарии (3)
St1ggy
06.08.2023 11:34MobX не панацея, есть легаси, которое сложно перевести на MobX, но легко на RTK
markelov69
06.08.2023 11:34MobX не панацея, есть легаси, которое сложно перевести на MobX, но легко на RTK
Ничего сложного, просто берешь и с начала вводишь MobX для новых задач и потихоньку заменяешь им все остальное.
markelov69
Этим людям будет полезно только одно, забыть уже об этом унылом гуано и просто использовать MobX и сразу все проблемы и заботы отпадут сами собой.