2023-01-03 19:55:46 +00:00
|
|
|
// Copyright 2020 Signal Messenger, LLC
|
2021-09-17 22:24:21 +00:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2021-10-26 19:15:33 +00:00
|
|
|
import type { ActionCreatorsMapObject } from 'redux';
|
2022-12-09 17:35:34 +00:00
|
|
|
import type { ThunkAction } from 'redux-thunk';
|
2021-10-26 19:15:33 +00:00
|
|
|
import { bindActionCreators } from 'redux';
|
2021-09-17 22:24:21 +00:00
|
|
|
import { useDispatch } from 'react-redux';
|
|
|
|
import { useMemo } from 'react';
|
|
|
|
|
2022-12-09 17:35:34 +00:00
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type-level function from an action creator (which may be ThunkAction creator) to a
|
|
|
|
* bound action creator.
|
|
|
|
*
|
|
|
|
* binding a thunk action creator changes it from:
|
|
|
|
* (params) => ThunkAction<R, ...>
|
|
|
|
* to:
|
|
|
|
* (params) => R
|
|
|
|
*
|
|
|
|
* a regular action creator's type is unchanged
|
|
|
|
*/
|
|
|
|
type BoundActionCreator<A> = A extends (
|
|
|
|
...params: infer P
|
|
|
|
) => ThunkAction<infer R, any, any, any>
|
|
|
|
? (...params: P) => R
|
|
|
|
: A;
|
|
|
|
|
|
|
|
export type BoundActionCreatorsMapObject<T extends ActionCreatorsMapObject> = {
|
|
|
|
[Property in keyof T]: BoundActionCreator<T[Property]>;
|
|
|
|
};
|
|
|
|
|
2021-09-17 22:24:21 +00:00
|
|
|
export const useBoundActions = <T extends ActionCreatorsMapObject>(
|
|
|
|
actions: T
|
2022-12-09 17:35:34 +00:00
|
|
|
): BoundActionCreatorsMapObject<T> => {
|
2021-09-17 22:24:21 +00:00
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
|
|
|
return useMemo(() => {
|
2022-12-09 17:35:34 +00:00
|
|
|
// bindActionCreators from redux has the wrong type when using thunk actions
|
|
|
|
// so we cast to the correct type
|
|
|
|
return bindActionCreators(
|
|
|
|
actions,
|
|
|
|
dispatch
|
|
|
|
) as any as BoundActionCreatorsMapObject<T>;
|
2021-09-17 22:24:21 +00:00
|
|
|
}, [actions, dispatch]);
|
|
|
|
};
|