-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuseDynamicModuleLoader.ts
50 lines (45 loc) · 1.53 KB
/
useDynamicModuleLoader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { useEffect } from 'react'
import { useStore } from 'react-redux'
import type { ReduxStoreWithReducerManager } from '@/app/providers/StoreProvider'
import type {
AsyncReducersList,
StateSchemaKey,
} from '@/app/providers/StoreProvider/config/stateSchema'
import { useAppDispatch } from '../useAppDispatch/useAppDispatch'
interface DynamicModuleLoaderOptions {
removeOnUnmount?: boolean
}
export const useDynamicModuleLoader = (
reducers: AsyncReducersList,
{ removeOnUnmount = true }: DynamicModuleLoaderOptions = {}
) => {
const dispatch = useAppDispatch()
const store = useStore() as ReduxStoreWithReducerManager
useEffect(() => {
const mountedReducers = store.reducerManager.getReducerMap()
Object.entries(reducers).forEach(([name, reducer]) => {
if (mountedReducers[name as StateSchemaKey]) return
// init reducer only if it is not mounted yet
store.reducerManager.add(
// reducers list type had StateSchemaKey as a name
name as StateSchemaKey,
reducer
)
dispatch({
type: `@INIT ${name} reducer`,
})
})
return () => {
if (!removeOnUnmount) return
Object.entries(reducers).forEach(([name]) => {
// reducers list type had StateSchemaKey as a name
store.reducerManager.remove(name as StateSchemaKey)
dispatch({
type: `@DESTROY ${name} reducer`,
})
})
}
// useEffect should be called only once when component is mounted
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}