@ -7,17 +7,21 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: rootReducer,
|
||||
middleware: getDefaultMiddleware =>
|
||||
getDefaultMiddleware().concat(
|
||||
loadingBarMiddleware({ promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'] }))
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware()
|
||||
.concat(
|
||||
loadingBarMiddleware({
|
||||
promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'],
|
||||
})
|
||||
)
|
||||
.concat(errorsMiddleware)
|
||||
.concat(soundsMiddleware()),
|
||||
});
|
||||
|
||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||
export type RootState = ReturnType<typeof rootReducer>
|
||||
export type RootState = ReturnType<typeof rootReducer>;
|
||||
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
|
||||
export type AppDispatch = typeof store.dispatch
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
|
@ -5,7 +5,9 @@ import { RootState } from '..';
|
||||
const defaultFailSuffix = 'FAIL';
|
||||
|
||||
export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
|
||||
({ dispatch }) => next => action => {
|
||||
({ dispatch }) =>
|
||||
(next) =>
|
||||
(action) => {
|
||||
if (action.type && !action.skipAlert) {
|
||||
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
||||
|
||||
|
@ -3,29 +3,40 @@ import { Middleware } from 'redux';
|
||||
import { RootState } from '..';
|
||||
|
||||
interface Config {
|
||||
promiseTypeSuffixes?: string[]
|
||||
promiseTypeSuffixes?: string[];
|
||||
}
|
||||
|
||||
const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = ['PENDING', 'FULFILLED', 'REJECTED'];
|
||||
const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
|
||||
'PENDING',
|
||||
'FULFILLED',
|
||||
'REJECTED',
|
||||
];
|
||||
|
||||
export const loadingBarMiddleware = (config: Config = {}): Middleware<Record<string, never>, RootState> => {
|
||||
export const loadingBarMiddleware = (
|
||||
config: Config = {}
|
||||
): Middleware<Record<string, never>, RootState> => {
|
||||
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes;
|
||||
|
||||
return ({ dispatch }) => next => (action) => {
|
||||
if (action.type && !action.skipLoading) {
|
||||
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes;
|
||||
return ({ dispatch }) =>
|
||||
(next) =>
|
||||
(action) => {
|
||||
if (action.type && !action.skipLoading) {
|
||||
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes;
|
||||
|
||||
const isPending = new RegExp(`${PENDING}$`, 'g');
|
||||
const isFulfilled = new RegExp(`${FULFILLED}$`, 'g');
|
||||
const isRejected = new RegExp(`${REJECTED}$`, 'g');
|
||||
const isPending = new RegExp(`${PENDING}$`, 'g');
|
||||
const isFulfilled = new RegExp(`${FULFILLED}$`, 'g');
|
||||
const isRejected = new RegExp(`${REJECTED}$`, 'g');
|
||||
|
||||
if (action.type.match(isPending)) {
|
||||
dispatch(showLoading());
|
||||
} else if (action.type.match(isFulfilled) || action.type.match(isRejected)) {
|
||||
dispatch(hideLoading());
|
||||
if (action.type.match(isPending)) {
|
||||
dispatch(showLoading());
|
||||
} else if (
|
||||
action.type.match(isFulfilled) ||
|
||||
action.type.match(isRejected)
|
||||
) {
|
||||
dispatch(hideLoading());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
||||
return next(action);
|
||||
};
|
||||
};
|
||||
|
@ -2,8 +2,8 @@ import { Middleware, AnyAction } from 'redux';
|
||||
import { RootState } from '..';
|
||||
|
||||
interface AudioSource {
|
||||
src: string
|
||||
type: string
|
||||
src: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const createAudio = (sources: AudioSource[]) => {
|
||||
@ -30,8 +30,11 @@ const play = (audio: HTMLAudioElement) => {
|
||||
audio.play();
|
||||
};
|
||||
|
||||
export const soundsMiddleware = (): Middleware<Record<string, never>, RootState> => {
|
||||
const soundCache: {[key: string]: HTMLAudioElement} = {
|
||||
export const soundsMiddleware = (): Middleware<
|
||||
Record<string, never>,
|
||||
RootState
|
||||
> => {
|
||||
const soundCache: { [key: string]: HTMLAudioElement } = {
|
||||
boop: createAudio([
|
||||
{
|
||||
src: '/sounds/boop.ogg',
|
||||
@ -44,7 +47,7 @@ export const soundsMiddleware = (): Middleware<Record<string, never>, RootState
|
||||
]),
|
||||
};
|
||||
|
||||
return () => next => (action: AnyAction) => {
|
||||
return () => (next) => (action: AnyAction) => {
|
||||
const sound = action?.meta?.sound;
|
||||
|
||||
if (sound && soundCache[sound]) {
|
||||
|
Reference in New Issue
Block a user