UNPKG

@wolf-tp/react-native-boilerplate

Version:

React Native Template

171 lines (153 loc) 4.89 kB
import { Action, Dispatch, Middleware } from '@reduxjs/toolkit'; import { onCheckType } from '../method/index'; export type Listener = (action: Action) => void; type ActionListenerContainer = { action: string; listener: Listener; }; const _subscribedBefore: Listener[] = []; const _subscribedAfter: Listener[] = []; const _actionsSubscribedBefore: ActionListenerContainer[] = []; const _actionsSubscribedAfter: ActionListenerContainer[] = []; const _subscribe = (listener: Listener, listenerContainer: Listener[]) => { if (!onCheckType(listener, 'function')) { throw new Error('Expected the listener to be a function.'); } listenerContainer.push(listener); return () => { const index = listenerContainer.indexOf(listener); listenerContainer.splice(index, 1); }; }; export const subscribeBefore = (listener: Listener) => { return _subscribe(listener, _subscribedBefore); }; export const subscribeAfter = (listener: Listener) => { return _subscribe(listener, _subscribedAfter); }; const _subscribeAction = ( actionListenerContainer: ActionListenerContainer, listenerContainer: ActionListenerContainer[], ) => { if (!onCheckType(actionListenerContainer.action, 'string')) { throw new Error('Expected the action to be a string.'); } if (!onCheckType(actionListenerContainer.listener, 'function')) { throw new Error('Expected the listener to be a function.'); } listenerContainer.push(actionListenerContainer); return () => { const index = listenerContainer.indexOf(actionListenerContainer); listenerContainer.splice(index, 1); }; }; export const subscribeActionBefore = (action: string, listener: Listener) => { const actionListenerContainer = { action, listener }; return _subscribeAction(actionListenerContainer, _actionsSubscribedBefore); }; export const subscribeActionAfter = (action: string, listener: Listener) => { const actionListenerContainer = { action, listener }; return _subscribeAction(actionListenerContainer, _actionsSubscribedAfter); }; export const unsubscribeBefore = () => { _subscribedBefore.length = 0; }; export const unsubscribeActionsBefore = () => { _actionsSubscribedBefore.length = 0; }; export const unsubscribeAfter = () => { _subscribedAfter.length = 0; }; export const unsubscribeActionsAfter = () => { _actionsSubscribedAfter.length = 0; }; export const unsubscribeAll = () => { unsubscribeBefore(); unsubscribeActionsBefore(); unsubscribeAfter(); unsubscribeActionsAfter(); }; const _unsubscribeAction = ( listenerContainer: ActionListenerContainer[], filterAction: string, ) => { const filteredListenerContainer = listenerContainer.filter( ({ action }) => action !== filterAction, ); listenerContainer.length = 0; listenerContainer.push(...filteredListenerContainer); }; export const unsubscribeActionBefore = (action: string) => { _unsubscribeAction(_actionsSubscribedBefore, action); }; export const unsubscribeActionAfter = (action: string) => { _unsubscribeAction(_actionsSubscribedAfter, action); }; export const unsubscribeActionAll = (action: string) => { unsubscribeActionBefore(action); unsubscribeActionAfter(action); }; const _callListeners = (action: Action, listenerContainer: Listener[]) => { for (let i = listenerContainer.length - 1; i >= 0; i--) { const listener = listenerContainer[i]; if (typeof action === 'object') { listener(action); } } }; const _callActionListeners = ( action: Action, listenerContainer: ActionListenerContainer[], ) => { for (let i = listenerContainer.length - 1; i >= 0; i--) { const listener = listenerContainer[i]; if ( action && onCheckType(action.type, 'string') && listener.action === action.type ) { listener.listener(action); } } }; export const subscribeActionMiddleware: Middleware = () => (next: Dispatch) => <A extends Action>(action: A) => { _callListeners(action, _subscribedBefore); _callActionListeners(action, _actionsSubscribedBefore); const result = next(action); _callListeners(action, _subscribedAfter); _callActionListeners(action, _actionsSubscribedAfter); return result; }; /** * Usage * * useEffect(() => { * const unsubscribe = subscribeAfter(action => * console.log(`Before state change action ${action.type}`), * ); * return () => { * unsubscribe(); * }; * }, []); * * useEffect(() => { * const unsubscribe = subscribeActionBefore('MY_ACTION_TYPE', action => * console.log(`Before state change action MY_ACTION_TYPE`), * ); * return () => { * unsubscribe(); * }; * }, []); * * useEffect(() => { * const unsubscribe = subscribeActionAfter('MY_ACTION_TYPE', action => * console.log(`After state change action MY_ACTION_TYPE`), * ); * return () => { * unsubscribe(); * }; * }, []); */