[Glitch] Upgrade Redux packages
Port a0e237a96f
to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
51d2d98174
commit
09376a8207
@ -1,6 +1,7 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { useEmoji } from '../../../actions/emojis';
|
import { useEmoji } from '../../../actions/emojis';
|
||||||
import { changeSetting } from '../../../actions/settings';
|
import { changeSetting } from '../../../actions/settings';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { changeComposeLanguage } from 'flavours/glitch/actions/compose';
|
import { changeComposeLanguage } from 'flavours/glitch/actions/compose';
|
||||||
import { useLanguage } from 'flavours/glitch/actions/languages';
|
import { useLanguage } from 'flavours/glitch/actions/languages';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { addReaction, removeReaction, dismissAnnouncement } from 'flavours/glitch/actions/announcements';
|
import { addReaction, removeReaction, dismissAnnouncement } from 'flavours/glitch/actions/announcements';
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ import { defineMessages, injectIntl } from 'react-intl';
|
|||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
|
import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
|
||||||
import { fetchLists } from 'flavours/glitch/actions/lists';
|
import { fetchLists } from 'flavours/glitch/actions/lists';
|
||||||
|
@ -6,9 +6,9 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { fetchAnnouncements, toggleShowAnnouncements } from 'flavours/glitch/actions/announcements';
|
import { fetchAnnouncements, toggleShowAnnouncements } from 'flavours/glitch/actions/announcements';
|
||||||
import { IconWithBadge } from 'flavours/glitch/components/icon_with_badge';
|
import { IconWithBadge } from 'flavours/glitch/components/icon_with_badge';
|
||||||
|
@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import { injectIntl } from 'react-intl';
|
import { injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { setupListAdder, resetListAdder } from '../../actions/lists';
|
import { setupListAdder, resetListAdder } from '../../actions/lists';
|
||||||
import NewListForm from '../lists/components/new_list_form';
|
import NewListForm from '../lists/components/new_list_form';
|
||||||
|
@ -4,10 +4,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { fetchLists } from 'flavours/glitch/actions/lists';
|
import { fetchLists } from 'flavours/glitch/actions/lists';
|
||||||
import ColumnBackButtonSlim from 'flavours/glitch/components/column_back_button_slim';
|
import ColumnBackButtonSlim from 'flavours/glitch/components/column_back_button_slim';
|
||||||
|
@ -6,10 +6,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ import { useCallback, useEffect, useRef } from 'react';
|
|||||||
|
|
||||||
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { OrderedSet, List as ImmutableList } from 'immutable';
|
import { OrderedSet, List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { shallowEqual } from 'react-redux';
|
import { shallowEqual } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ import classNames from 'classnames';
|
|||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
|
import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { followAccount } from 'flavours/glitch/actions/accounts';
|
import { followAccount } from 'flavours/glitch/actions/accounts';
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { fetchLists } from 'flavours/glitch/actions/lists';
|
import { fetchLists } from 'flavours/glitch/actions/lists';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import type { Reducer } from 'redux';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
followAccountSuccess,
|
followAccountSuccess,
|
||||||
unfollowAccountSuccess,
|
unfollowAccountSuccess,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Record as ImmutableRecord, Stack } from 'immutable';
|
|
||||||
|
|
||||||
import type { Reducer } from '@reduxjs/toolkit';
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
|
import { Record as ImmutableRecord, Stack } from 'immutable';
|
||||||
|
|
||||||
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
|
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
|
||||||
import type { ModalType } from '../actions/modal';
|
import type { ModalType } from '../actions/modal';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Map as ImmutableMap } from 'immutable';
|
|
||||||
|
|
||||||
import { isFulfilled } from '@reduxjs/toolkit';
|
import { isFulfilled } from '@reduxjs/toolkit';
|
||||||
import type { Reducer } from 'redux';
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships';
|
import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships';
|
||||||
import type { Account } from 'flavours/glitch/models/account';
|
import type { Account } from 'flavours/glitch/models/account';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Record as ImmutableRecord } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { accountDefaultValues } from 'flavours/glitch/models/account';
|
import { accountDefaultValues } from 'flavours/glitch/models/account';
|
||||||
import type { Account, AccountShape } from 'flavours/glitch/models/account';
|
import type { Account, AccountShape } from 'flavours/glitch/models/account';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { toServerSideType } from 'flavours/glitch/utils/filters';
|
import { toServerSideType } from 'flavours/glitch/utils/filters';
|
||||||
|
|
||||||
|
@ -1,20 +1,34 @@
|
|||||||
import type { AnyAction, Middleware } from 'redux';
|
import { isAction } from '@reduxjs/toolkit';
|
||||||
|
import type { Action, Middleware } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import type { RootState } from '..';
|
import type { RootState } from '..';
|
||||||
import { showAlertForError } from '../../actions/alerts';
|
import { showAlertForError } from '../../actions/alerts';
|
||||||
|
|
||||||
const defaultFailSuffix = 'FAIL';
|
const defaultFailSuffix = 'FAIL';
|
||||||
|
const isFailedAction = new RegExp(`${defaultFailSuffix}$`, 'g');
|
||||||
|
|
||||||
export const errorsMiddleware: Middleware<unknown, RootState> =
|
interface ActionWithMaybeAlertParams extends Action {
|
||||||
|
skipAlert?: boolean;
|
||||||
|
skipNotFound?: boolean;
|
||||||
|
error?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithmaybeAlertParams(
|
||||||
|
action: unknown,
|
||||||
|
): action is ActionWithMaybeAlertParams {
|
||||||
|
return isAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
|
||||||
({ dispatch }) =>
|
({ dispatch }) =>
|
||||||
(next) =>
|
(next) =>
|
||||||
(action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => {
|
(action) => {
|
||||||
if (action.type && !action.skipAlert) {
|
if (
|
||||||
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
isActionWithmaybeAlertParams(action) &&
|
||||||
|
!action.skipAlert &&
|
||||||
if (typeof action.type === 'string' && action.type.match(isFail)) {
|
action.type.match(isFailedAction)
|
||||||
dispatch(showAlertForError(action.error, action.skipNotFound));
|
) {
|
||||||
}
|
dispatch(showAlertForError(action.error, action.skipNotFound));
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
|
@ -3,9 +3,11 @@ import {
|
|||||||
isPending as isThunkActionPending,
|
isPending as isThunkActionPending,
|
||||||
isFulfilled as isThunkActionFulfilled,
|
isFulfilled as isThunkActionFulfilled,
|
||||||
isRejected as isThunkActionRejected,
|
isRejected as isThunkActionRejected,
|
||||||
|
isAction,
|
||||||
} from '@reduxjs/toolkit';
|
} from '@reduxjs/toolkit';
|
||||||
|
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { showLoading, hideLoading } from 'react-redux-loading-bar';
|
import { showLoading, hideLoading } from 'react-redux-loading-bar';
|
||||||
import type { AnyAction, Middleware } from 'redux';
|
|
||||||
|
|
||||||
import type { RootState } from '..';
|
import type { RootState } from '..';
|
||||||
|
|
||||||
@ -19,14 +21,28 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
|
|||||||
'REJECTED',
|
'REJECTED',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface ActionWithSkipLoading extends UnknownAction {
|
||||||
|
skipLoading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithSkipLoading(
|
||||||
|
action: unknown,
|
||||||
|
): action is ActionWithSkipLoading {
|
||||||
|
return (
|
||||||
|
isAction(action) &&
|
||||||
|
'skipLoading' in action &&
|
||||||
|
typeof action.skipLoading === 'boolean'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const loadingBarMiddleware = (
|
export const loadingBarMiddleware = (
|
||||||
config: Config = {},
|
config: Config = {},
|
||||||
): Middleware<unknown, RootState> => {
|
): Middleware<{ skipLoading?: boolean }, RootState> => {
|
||||||
const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
|
const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
|
||||||
|
|
||||||
return ({ dispatch }) =>
|
return ({ dispatch }) =>
|
||||||
(next) =>
|
(next) =>
|
||||||
(action: AnyAction) => {
|
(action) => {
|
||||||
let isPending = false;
|
let isPending = false;
|
||||||
let isFulfilled = false;
|
let isFulfilled = false;
|
||||||
let isRejected = false;
|
let isRejected = false;
|
||||||
@ -39,7 +55,7 @@ export const loadingBarMiddleware = (
|
|||||||
else if (isThunkActionFulfilled(action)) isFulfilled = true;
|
else if (isThunkActionFulfilled(action)) isFulfilled = true;
|
||||||
else if (isThunkActionRejected(action)) isRejected = true;
|
else if (isThunkActionRejected(action)) isRejected = true;
|
||||||
} else if (
|
} else if (
|
||||||
action.type &&
|
isActionWithSkipLoading(action) &&
|
||||||
!action.skipLoading &&
|
!action.skipLoading &&
|
||||||
typeof action.type === 'string'
|
typeof action.type === 'string'
|
||||||
) {
|
) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import type { Middleware, AnyAction } from 'redux';
|
import { isAction } from '@reduxjs/toolkit';
|
||||||
|
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import ready from 'flavours/glitch/ready';
|
import ready from 'flavours/glitch/ready';
|
||||||
import { assetHost } from 'flavours/glitch/utils/config';
|
import { assetHost } from 'flavours/glitch/utils/config';
|
||||||
@ -10,6 +11,21 @@ interface AudioSource {
|
|||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ActionWithMetaSound extends UnknownAction {
|
||||||
|
meta: { sound: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithMetaSound(action: unknown): action is ActionWithMetaSound {
|
||||||
|
return (
|
||||||
|
isAction(action) &&
|
||||||
|
'meta' in action &&
|
||||||
|
typeof action.meta === 'object' &&
|
||||||
|
!!action.meta &&
|
||||||
|
'sound' in action.meta &&
|
||||||
|
typeof action.meta.sound === 'string'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const createAudio = (sources: AudioSource[]) => {
|
const createAudio = (sources: AudioSource[]) => {
|
||||||
const audio = new Audio();
|
const audio = new Audio();
|
||||||
sources.forEach(({ type, src }) => {
|
sources.forEach(({ type, src }) => {
|
||||||
@ -34,7 +50,10 @@ const play = (audio: HTMLAudioElement) => {
|
|||||||
void audio.play();
|
void audio.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const soundsMiddleware = (): Middleware<unknown, RootState> => {
|
export const soundsMiddleware = (): Middleware<
|
||||||
|
Record<string, never>,
|
||||||
|
RootState
|
||||||
|
> => {
|
||||||
const soundCache: Record<string, HTMLAudioElement> = {};
|
const soundCache: Record<string, HTMLAudioElement> = {};
|
||||||
|
|
||||||
void ready(() => {
|
void ready(() => {
|
||||||
@ -50,15 +69,15 @@ export const soundsMiddleware = (): Middleware<unknown, RootState> => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () =>
|
return () => (next) => (action) => {
|
||||||
(next) =>
|
if (isActionWithMetaSound(action)) {
|
||||||
(action: AnyAction & { meta?: { sound?: string } }) => {
|
const sound = action.meta.sound;
|
||||||
const sound = action.meta?.sound;
|
|
||||||
|
|
||||||
if (sound && Object.hasOwn(soundCache, sound)) {
|
if (sound && Object.hasOwn(soundCache, sound)) {
|
||||||
play(soundCache[sound]);
|
play(soundCache[sound]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { TypedUseSelectorHook } from 'react-redux';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import type { TypedUseSelectorHook } from 'react-redux';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import type { AppDispatch, RootState } from './store';
|
import type { AppDispatch, RootState } from './store';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user