@chhsiao1981/use-thunk 10.3.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ThunkContext.d.ts +7 -0
- package/dist/createReducer.d.ts +4 -0
- package/dist/createThunk.d.ts +4 -0
- package/dist/dispatch.d.ts +4 -0
- package/dist/dispatchFuncMap.d.ts +18 -0
- package/dist/genUUID.d.ts +1 -0
- package/dist/index.d.ts +15 -0
- package/{types → dist}/init.d.ts +0 -3
- package/dist/reduceMap.d.ts +6 -0
- package/dist/reducer.d.ts +5 -0
- package/dist/remove.d.ts +5 -0
- package/dist/setDefaultID.d.ts +5 -0
- package/dist/stateTypes.d.ts +16 -0
- package/dist/states.d.ts +9 -0
- package/{types → dist}/thunk.d.ts +6 -3
- package/dist/thunkContextMap.d.ts +15 -0
- package/dist/thunkContextTypes.d.ts +8 -0
- package/{types → dist}/thunkModuleFuncMap.d.ts +1 -0
- package/dist/update.d.ts +6 -0
- package/dist/useThunk.d.ts +12 -0
- package/dist/useThunkReducer.d.ts +17 -0
- package/package.json +2 -2
- package/src/ThunkContext.tsx +23 -18
- package/src/action/ActionOrThunk.ts +5 -0
- package/src/action/baseAction.ts +6 -0
- package/src/action/index.ts +16 -0
- package/src/action/thunk.ts +5 -0
- package/src/createReducer.ts +7 -7
- package/src/createThunk.ts +31 -0
- package/src/index.ts +21 -27
- package/src/init/index.ts +26 -0
- package/src/init/initCore.ts +31 -0
- package/src/reduceMap.ts +3 -4
- package/src/reducer.ts +4 -4
- package/src/remove.ts +10 -25
- package/src/set.ts +7 -0
- package/src/setDefaultID.ts +5 -5
- package/src/setMap.ts +65 -0
- package/src/stateTypes.ts +4 -3
- package/src/states.ts +17 -17
- package/src/thunkContextMap.ts +4 -4
- package/src/thunkContextTypes.ts +4 -4
- package/src/thunkModule/defaultThunkModuleFuncMap.ts +16 -0
- package/src/thunkModule/index.ts +21 -0
- package/src/update.ts +31 -0
- package/src/useThunk.ts +25 -45
- package/src/useThunkReducer.ts +34 -43
- package/types/ThunkContext.d.ts +4 -4
- package/types/action/ActionOrThunk.d.ts +4 -0
- package/types/action/baseAction.d.ts +5 -0
- package/types/action/index.d.ts +8 -0
- package/types/action/thunk.d.ts +3 -0
- package/types/createThunk.d.ts +5 -0
- package/types/dispatch.d.ts +1 -1
- package/types/dispatchFuncMap.d.ts +4 -5
- package/types/index.d.ts +14 -8
- package/types/init/index.d.ts +7 -0
- package/types/init/initCore.d.ts +9 -0
- package/types/reducer.d.ts +4 -4
- package/types/remove.d.ts +4 -4
- package/types/set.d.ts +4 -0
- package/types/setDefaultID.d.ts +3 -3
- package/types/setMap.d.ts +17 -0
- package/types/stateTypes.d.ts +3 -2
- package/types/states.d.ts +8 -8
- package/types/thunkContextMap.d.ts +4 -4
- package/types/thunkContextTypes.d.ts +4 -4
- package/types/thunkModule/defaultThunkModuleFuncMap.d.ts +5 -0
- package/types/thunkModule/index.d.ts +16 -0
- package/types/update.d.ts +6 -0
- package/types/useThunk.d.ts +5 -8
- package/types/useThunkReducer.d.ts +5 -11
- package/dist/index.js +0 -1723
- package/dist/index.umd.cjs +0 -50
- package/src/action.ts +0 -20
- package/src/dispatch.ts +0 -6
- package/src/dispatchFuncMap.ts +0 -66
- package/src/init.ts +0 -64
- package/src/registerThunk.ts +0 -36
- package/src/setData.ts +0 -26
- package/src/thunk.ts +0 -16
- package/src/thunkModuleFuncMap.ts +0 -11
- package/types/registerThunk.d.ts +0 -4
- package/types/setData.d.ts +0 -5
- /package/{types → dist}/action.d.ts +0 -0
package/src/remove.ts
CHANGED
|
@@ -1,47 +1,32 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
export const remove = <S extends State>(myID: string): Thunk<S> => {
|
|
5
|
-
return (dispatch, getClassState) => {
|
|
6
|
-
const state = getClassState()
|
|
7
|
-
const {
|
|
8
|
-
nodes: { [myID]: me },
|
|
9
|
-
} = state
|
|
10
|
-
if (!me) {
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// remove me from myClass list
|
|
15
|
-
dispatch(removeCore(myID))
|
|
16
|
-
}
|
|
17
|
-
}
|
|
1
|
+
import type BaseAction from './action/baseAction'
|
|
2
|
+
import type { ModuleState, NodeStateMap, State } from './stateTypes'
|
|
18
3
|
|
|
19
4
|
export const REMOVE = '@chhsiao1981/use-thunk/REMOVE'
|
|
20
|
-
const
|
|
5
|
+
export const remove = (myID: string): BaseAction => ({
|
|
21
6
|
myID,
|
|
22
7
|
type: REMOVE,
|
|
23
8
|
})
|
|
24
9
|
|
|
25
10
|
export const reduceRemove = <S extends State>(
|
|
26
|
-
|
|
11
|
+
moduleState: ModuleState<S>,
|
|
27
12
|
action: BaseAction,
|
|
28
|
-
):
|
|
13
|
+
): ModuleState<S> => {
|
|
29
14
|
const { myID } = action
|
|
30
15
|
|
|
31
|
-
const myNode =
|
|
16
|
+
const myNode = moduleState.nodes[myID]
|
|
32
17
|
if (!myNode) {
|
|
33
|
-
return
|
|
18
|
+
return moduleState
|
|
34
19
|
}
|
|
35
20
|
|
|
36
|
-
const newNodes = Object.keys(
|
|
21
|
+
const newNodes = Object.keys(moduleState.nodes)
|
|
37
22
|
.filter((each) => each !== myID)
|
|
38
23
|
.reduce((r: NodeStateMap<S>, x) => {
|
|
39
|
-
r[x] =
|
|
24
|
+
r[x] = moduleState.nodes[x]
|
|
40
25
|
return r
|
|
41
26
|
}, {})
|
|
42
27
|
|
|
43
28
|
// defaultID
|
|
44
|
-
const newState = Object.assign({},
|
|
29
|
+
const newState = Object.assign({}, moduleState, { nodes: newNodes })
|
|
45
30
|
if (newState.defaultID === myID) {
|
|
46
31
|
newState.defaultID = null
|
|
47
32
|
}
|
package/src/set.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Dispatch } from 'react'
|
|
2
|
+
// XXX requiring to import directly from action/ActionOrThunk, or it will cause looping.
|
|
3
|
+
import type { ActionOrThunk } from './action/ActionOrThunk'
|
|
4
|
+
import type { State } from './stateTypes'
|
|
5
|
+
|
|
6
|
+
// set
|
|
7
|
+
export type set<S extends State> = Dispatch<ActionOrThunk<S>>
|
package/src/setDefaultID.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
1
|
+
import type BaseAction from './action/baseAction'
|
|
2
|
+
import type { ModuleState, State } from './stateTypes'
|
|
3
3
|
|
|
4
4
|
export const SET_DEFAULT_ID = '@chhsiao1981/use-thunk/SET_DEFAULT_ID'
|
|
5
5
|
export const setDefaultID = (myID: string): BaseAction => ({
|
|
@@ -8,10 +8,10 @@ export const setDefaultID = (myID: string): BaseAction => ({
|
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
export const reduceSetDefaultID = <S extends State>(
|
|
11
|
-
|
|
11
|
+
moduleState: ModuleState<S>,
|
|
12
12
|
action: BaseAction,
|
|
13
|
-
):
|
|
13
|
+
): ModuleState<S> => {
|
|
14
14
|
const { myID } = action
|
|
15
15
|
|
|
16
|
-
return Object.assign({},
|
|
16
|
+
return Object.assign({}, moduleState, { defaultID: myID })
|
|
17
17
|
}
|
package/src/setMap.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ActionFunc } from './action'
|
|
2
|
+
import type { set } from './set'
|
|
3
|
+
import type { State } from './stateTypes'
|
|
4
|
+
import type { ThunkModule, ThunkModuleFunc } from './thunkModule'
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_THUNK_MODULE_FUNC_MAP,
|
|
7
|
+
type DefaultThunkModuleFuncMap,
|
|
8
|
+
} from './thunkModule/defaultThunkModuleFuncMap'
|
|
9
|
+
|
|
10
|
+
// biome-ignore lint/suspicious/noExplicitAny: unknown requires same type in list, use any for possible different types.
|
|
11
|
+
type VoidReturnType<T extends (...params: any[]) => unknown> = (...params: Parameters<T>) => void
|
|
12
|
+
|
|
13
|
+
export type setMap<S extends State, T extends ThunkModuleFunc<S>> = {
|
|
14
|
+
[action in keyof T]: VoidReturnType<T[action]>
|
|
15
|
+
} & Omit<DefaultSetMap, keyof T>
|
|
16
|
+
|
|
17
|
+
export type DefaultSetMap = {
|
|
18
|
+
[action in keyof DefaultThunkModuleFuncMap]: VoidReturnType<DefaultThunkModuleFuncMap[action]>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface setMapByModuleMap<S extends State, T extends ThunkModuleFunc<S>> {
|
|
22
|
+
[name: string]: setMap<S, T>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// biome-ignore lint/suspicious/noExplicitAny: set map by module map can be any.
|
|
26
|
+
export const SET_MAP_BY_MODULE_MAP: setMapByModuleMap<any, any> = {}
|
|
27
|
+
|
|
28
|
+
export const constructSetMap = <S extends State, T extends ThunkModuleFunc<S>>(
|
|
29
|
+
theDo: ThunkModule<S>,
|
|
30
|
+
set: set<S>,
|
|
31
|
+
setMap: setMap<S, T>,
|
|
32
|
+
) => {
|
|
33
|
+
Object.keys(theDo)
|
|
34
|
+
// default and name are reserved words.
|
|
35
|
+
// functions starting reduce are included in default and not exported.
|
|
36
|
+
.filter((each) => typeof theDo[each] === 'function')
|
|
37
|
+
.reduce((val, eachAction) => {
|
|
38
|
+
if (val[eachAction]) {
|
|
39
|
+
return val
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// because action is a function.
|
|
43
|
+
const action = theDo[eachAction] as ActionFunc<S>
|
|
44
|
+
|
|
45
|
+
// @ts-expect-error eachAction is in setMap<S, R>
|
|
46
|
+
// biome-ignore lint/suspicious/noExplicitAny: action parameters can be any types.
|
|
47
|
+
val[eachAction] = (...params: any[]) => set(action(...params))
|
|
48
|
+
return val
|
|
49
|
+
}, setMap)
|
|
50
|
+
|
|
51
|
+
Object.keys(DEFAULT_THUNK_MODULE_FUNC_MAP).reduce((val, eachAction) => {
|
|
52
|
+
if (val[eachAction]) {
|
|
53
|
+
return val
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const action = DEFAULT_THUNK_MODULE_FUNC_MAP[eachAction]
|
|
57
|
+
|
|
58
|
+
// @ts-expect-error eachAction is in setMap<S, R>
|
|
59
|
+
// biome-ignore lint/suspicious/noExplicitAny: action parameters can be any types.
|
|
60
|
+
val[eachAction] = (...params: any[]) => set(action(...params))
|
|
61
|
+
return val
|
|
62
|
+
}, setMap)
|
|
63
|
+
|
|
64
|
+
return setMap
|
|
65
|
+
}
|
package/src/stateTypes.ts
CHANGED
|
@@ -13,9 +13,10 @@ export type NodeStateMap<S extends State> = {
|
|
|
13
13
|
[key: string]: NodeState<S>
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
export type
|
|
18
|
-
|
|
16
|
+
// ModuleState
|
|
17
|
+
export type ModuleState<S extends State> = {
|
|
18
|
+
name?: string
|
|
19
|
+
myClass?: string // XXX to deprecated
|
|
19
20
|
defaultID?: string | null
|
|
20
21
|
nodes: NodeStateMap<S>
|
|
21
22
|
defaultState: S
|
package/src/states.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type { ThunkModuleFunc } from './
|
|
1
|
+
import type { setMap } from './setMap'
|
|
2
|
+
import type { ModuleState, NodeState, State } from './stateTypes'
|
|
3
|
+
import type { ThunkModuleFunc } from './thunkModule'
|
|
4
4
|
import type { UseThunk } from './useThunk'
|
|
5
5
|
|
|
6
|
-
export const getDefaultID = <S extends State>(
|
|
7
|
-
return
|
|
6
|
+
export const getDefaultID = <S extends State>(moduleState: ModuleState<S>): string => {
|
|
7
|
+
return moduleState.defaultID ?? ''
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export const getNode = <S extends State>(
|
|
11
|
-
|
|
11
|
+
moduleState: ModuleState<S>,
|
|
12
12
|
myID?: string,
|
|
13
13
|
): NodeState<S> | null => {
|
|
14
|
-
const theID = myID ? myID : getDefaultID(
|
|
14
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
15
15
|
if (!theID) {
|
|
16
16
|
return null
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
return
|
|
19
|
+
return moduleState.nodes[theID] || null
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export const getState = <S extends State>(
|
|
23
|
-
const theID = myID ? myID : getDefaultID(
|
|
22
|
+
export const getState = <S extends State>(moduleState: ModuleState<S>, myID?: string): S | null => {
|
|
23
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
24
24
|
if (!theID) {
|
|
25
25
|
return null
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const me =
|
|
28
|
+
const me = moduleState.nodes[theID]
|
|
29
29
|
if (!me) {
|
|
30
30
|
return null
|
|
31
31
|
}
|
|
32
32
|
return me.state
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export const mustGetState = <S extends State>(
|
|
36
|
-
return getState(
|
|
35
|
+
export const mustGetState = <S extends State>(moduleState: ModuleState<S>, myID?: string): S => {
|
|
36
|
+
return getState(moduleState, myID) || moduleState.defaultState
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export const mustGetStateByThunk = <S extends State, R extends ThunkModuleFunc<S>>(
|
|
40
40
|
theUseThunk: UseThunk<S, R>,
|
|
41
41
|
myID?: string,
|
|
42
|
-
): [S,
|
|
43
|
-
const [
|
|
44
|
-
const theID = myID ? myID : getDefaultID(
|
|
45
|
-
const state = mustGetState(
|
|
42
|
+
): [S, setMap<S, R>, string] => {
|
|
43
|
+
const [moduleState, theDo] = theUseThunk
|
|
44
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
45
|
+
const state = mustGetState(moduleState, theID)
|
|
46
46
|
return [state, theDo, theID]
|
|
47
47
|
}
|
package/src/thunkContextMap.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { Context as rContext } from 'react'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ModuleState } from './stateTypes'
|
|
3
3
|
import type { Context } from './thunkContextTypes'
|
|
4
4
|
|
|
5
5
|
export type ThunkContextMap = {
|
|
6
6
|
theMap: {
|
|
7
|
-
[
|
|
7
|
+
[moduleName: string]: {
|
|
8
8
|
// biome-ignore lint/suspicious/noExplicitAny: ThunkContextMap can be any type
|
|
9
9
|
context: rContext<Context<any>>
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// we need to use refModuleState to sync all the moduleState in all ops.
|
|
12
12
|
// biome-ignore lint/suspicious/noExplicitAny: ThunkContextMap can be any type
|
|
13
|
-
|
|
13
|
+
refModuleState: { current: ModuleState<any> }
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
theList: string[]
|
package/src/thunkContextTypes.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Dispatch, SetStateAction } from 'react'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ModuleState, State } from './stateTypes'
|
|
3
3
|
|
|
4
4
|
export type Context<S extends State> = {
|
|
5
|
-
// INFO: we use
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
// INFO: we use refModuleState to reference across all the useThunk of the same module in different ops.
|
|
6
|
+
refModuleState: { current: ModuleState<S> }
|
|
7
|
+
setModuleState: Dispatch<SetStateAction<ModuleState<S>>>
|
|
8
8
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ActionFunc } from '../action'
|
|
2
|
+
import { init } from '../init'
|
|
3
|
+
import { remove } from '../remove'
|
|
4
|
+
import { setData, update } from '../update'
|
|
5
|
+
|
|
6
|
+
export const DEFAULT_THUNK_MODULE_FUNC_MAP: DefaultThunkModuleFuncMap = {
|
|
7
|
+
init,
|
|
8
|
+
update,
|
|
9
|
+
setData,
|
|
10
|
+
remove,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type DefaultThunkModuleFuncMap = {
|
|
14
|
+
// biome-ignore lint/suspicious/noExplicitAny: DefaultThunkModuleFuncMap can be any type.
|
|
15
|
+
[action: string]: ActionFunc<any>
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ThunkFunc } from '../action'
|
|
2
|
+
import type { Reducer } from '../reducer'
|
|
3
|
+
import type { State } from '../stateTypes'
|
|
4
|
+
|
|
5
|
+
export interface ThunkModuleBase<S extends State> {
|
|
6
|
+
[idx: string]: ThunkFunc<S> | string | Reducer<S> | S | undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ThunkModuleFunc<S extends State> extends ThunkModuleBase<S> {
|
|
10
|
+
[action: string]: ThunkFunc<S>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// This is used as the parameter for useThunk.
|
|
14
|
+
export type ThunkModule<S extends State> = {
|
|
15
|
+
name?: string
|
|
16
|
+
myClass?: string // XXX to deprecate
|
|
17
|
+
default?: Reducer<S>
|
|
18
|
+
defaultState: S
|
|
19
|
+
} & ThunkModuleBase<S>
|
|
20
|
+
|
|
21
|
+
export type ThunkModuleToFunc<T> = Omit<T, 'name' | 'myClass' | 'default' | 'defaultState'>
|
package/src/update.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type BaseAction from './action/baseAction'
|
|
2
|
+
import type { ModuleState, State } from './stateTypes'
|
|
3
|
+
|
|
4
|
+
export const UPDATE = '@chhsiao1981/use-thunk/UPDATE'
|
|
5
|
+
export const update = <S extends State>(myID: string, data: Partial<S>): BaseAction => ({
|
|
6
|
+
myID,
|
|
7
|
+
type: UPDATE,
|
|
8
|
+
data,
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export const setData = <S extends State>(myID: string, data: Partial<S>): BaseAction => {
|
|
12
|
+
console.warn('setData will be deprecated in the next version.')
|
|
13
|
+
return update(myID, data)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const reduceUpdate = <S extends State>(
|
|
17
|
+
moduleState: ModuleState<S>,
|
|
18
|
+
action: BaseAction,
|
|
19
|
+
): ModuleState<S> => {
|
|
20
|
+
const { myID, data } = action
|
|
21
|
+
|
|
22
|
+
const myNode = moduleState.nodes[myID]
|
|
23
|
+
if (!myNode) return moduleState
|
|
24
|
+
|
|
25
|
+
const newMyState = Object.assign({}, myNode.state, data)
|
|
26
|
+
const newMyNode = Object.assign({}, myNode, { state: newMyState })
|
|
27
|
+
const newNodes = Object.assign({}, moduleState.nodes, { [myID]: newMyNode })
|
|
28
|
+
const newModuleState = Object.assign({}, moduleState, { nodes: newNodes })
|
|
29
|
+
|
|
30
|
+
return newModuleState
|
|
31
|
+
}
|
package/src/useThunk.ts
CHANGED
|
@@ -1,71 +1,51 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import { createReducer } from './createReducer'
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type DispatchFuncMapByClassMap,
|
|
7
|
-
} from './dispatchFuncMap'
|
|
8
|
-
import type { ClassState, State } from './stateTypes'
|
|
9
|
-
import type { ThunkModule, ThunkModuleFunc } from './thunk'
|
|
3
|
+
import { constructSetMap, type setMap, type setMapByModuleMap } from './setMap'
|
|
4
|
+
import type { ModuleState, State } from './stateTypes'
|
|
5
|
+
import type { ThunkModule, ThunkModuleFunc } from './thunkModule'
|
|
10
6
|
import useThunkReducer from './useThunkReducer'
|
|
11
7
|
|
|
12
|
-
// biome-ignore lint/suspicious/noExplicitAny:
|
|
13
|
-
const
|
|
8
|
+
// biome-ignore lint/suspicious/noExplicitAny: SET_MAP_BY_MODULE can by any type
|
|
9
|
+
const SET_MAP_BY_MODULE: setMapByModuleMap<any, any> = {}
|
|
14
10
|
|
|
15
|
-
export type UseThunk<S extends State, R extends ThunkModuleFunc<S>> = [
|
|
16
|
-
ClassState<S>,
|
|
17
|
-
DispatchFuncMap<S, R>,
|
|
18
|
-
]
|
|
11
|
+
export type UseThunk<S extends State, R extends ThunkModuleFunc<S>> = [ModuleState<S>, setMap<S, R>]
|
|
19
12
|
|
|
20
13
|
/**********
|
|
21
14
|
* useThunk
|
|
22
15
|
**********/
|
|
23
16
|
export default <S extends State, R extends ThunkModuleFunc<S>>(
|
|
24
|
-
theDo: ThunkModule<S
|
|
17
|
+
theDo: ThunkModule<S>,
|
|
25
18
|
): UseThunk<S, R> => {
|
|
26
|
-
const { myClass } = theDo
|
|
19
|
+
const { name: propsName, myClass } = theDo
|
|
20
|
+
const name = (propsName ? propsName : myClass) || ''
|
|
27
21
|
|
|
28
|
-
// 1.
|
|
29
|
-
|
|
30
|
-
// INFO The reason why we need to useRef is because we don't want to
|
|
31
|
-
// rebuild dispatchMap every time we call useThunk.
|
|
32
|
-
const dispatchMapByClass: DispatchFuncMapByClassMap<S, R> = DISPACH_MAP_BY_CLASS
|
|
33
|
-
|
|
34
|
-
// 2. It requires shared nodes for the same class to have the same dispatchMap.
|
|
35
|
-
// We don't optimize the dispatchMap in this PR.
|
|
36
|
-
const isFirstTime = !dispatchMapByClass[myClass]
|
|
22
|
+
// 1. It requires shared nodes for the same module to have the same setMap.
|
|
23
|
+
const isFirstTime = !SET_MAP_BY_MODULE[name]
|
|
37
24
|
if (isFirstTime) {
|
|
38
|
-
|
|
39
|
-
dispatchMapByClass[myClass] = {}
|
|
25
|
+
SET_MAP_BY_MODULE[name] = {}
|
|
40
26
|
}
|
|
41
|
-
const
|
|
27
|
+
const setMap = SET_MAP_BY_MODULE[name] as setMap<S, R>
|
|
42
28
|
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
// having ClassState as the input. It is ok to have
|
|
51
|
-
// different reducers within the same class.
|
|
52
|
-
//
|
|
53
|
-
// INFO useMemo is to avoid accidental re-init createReducer every-time.
|
|
54
|
-
const theReducer = useMemo(() => theDo.default ?? createReducer<S>(), [])
|
|
29
|
+
// 2. reducer.
|
|
30
|
+
// theReducer is different for different useThunk,
|
|
31
|
+
// even within the same module.
|
|
32
|
+
// However, because theReducer is a pure function by
|
|
33
|
+
// having ModuleState as the input. It is ok to have
|
|
34
|
+
// different reducers within the same module.
|
|
35
|
+
const theReducer = useMemo(() => createReducer<S>(), [])
|
|
55
36
|
|
|
56
|
-
//
|
|
57
|
-
const [
|
|
37
|
+
// 3. useThunkReducer
|
|
38
|
+
const [moduleState, set] = useThunkReducer(theReducer, name)
|
|
58
39
|
|
|
59
|
-
// INFO useMemo is to avoid accidental included in useEffect.
|
|
60
40
|
const ret: UseThunk<S, R> = useMemo(() => {
|
|
61
|
-
return [
|
|
62
|
-
}, [
|
|
41
|
+
return [moduleState, setMap]
|
|
42
|
+
}, [moduleState, setMap])
|
|
63
43
|
|
|
64
44
|
if (!isFirstTime) {
|
|
65
45
|
return ret
|
|
66
46
|
}
|
|
67
47
|
|
|
68
|
-
|
|
48
|
+
constructSetMap(theDo, set, setMap)
|
|
69
49
|
|
|
70
50
|
return ret
|
|
71
51
|
}
|
package/src/useThunkReducer.ts
CHANGED
|
@@ -1,69 +1,60 @@
|
|
|
1
1
|
//https://medium.com/solute-labs/configuring-thunk-action-creators-and-redux-dev-tools-with-reacts-usereducer-hook-5a1608476812
|
|
2
2
|
//https://github.com/nathanbuchar/react-hook-thunk-reducer/blob/master/src/thunk-reducer.js
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import type
|
|
6
|
-
import type {
|
|
4
|
+
import { useCallback, useContext } from 'react'
|
|
5
|
+
import type BaseAction from './action/baseAction'
|
|
6
|
+
import type { Reducer } from './reducer'
|
|
7
|
+
import type { set } from './set'
|
|
8
|
+
import type { ModuleState, State } from './stateTypes'
|
|
7
9
|
import { THUNK_CONTEXT_MAP } from './thunkContextMap'
|
|
8
10
|
|
|
9
|
-
export type Thunk<S extends State, A extends BaseAction> = (
|
|
10
|
-
dispatch: Dispatch<ActionOrThunk<S, A>>,
|
|
11
|
-
getClassState: () => ClassState<S>,
|
|
12
|
-
) => void
|
|
13
|
-
|
|
14
|
-
export type ActionOrThunk<S extends State, A extends BaseAction> = A | Thunk<S, A>
|
|
15
11
|
/**
|
|
16
12
|
* useThunkReducer
|
|
17
13
|
*
|
|
18
14
|
* Augments React's useReducer() hook so that the action
|
|
19
|
-
* dispatcher supports thunks.
|
|
20
|
-
*
|
|
21
|
-
* @param {Function} reducer
|
|
22
|
-
* @param {string} className
|
|
23
|
-
* @returns {[ClassState<S>, Dispatch]}
|
|
15
|
+
* setter (dispatcher) supports thunks.
|
|
24
16
|
*/
|
|
25
|
-
export default <S extends State
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
(newClassState: ClassState<S>) => {
|
|
38
|
-
refClassState.current = newClassState
|
|
39
|
-
setClassState_c(newClassState)
|
|
17
|
+
export default <S extends State>(reducer: Reducer<S>, moduleName: string): [ModuleState<S>, set<S>] => {
|
|
18
|
+
const { context } = THUNK_CONTEXT_MAP.theMap[moduleName]
|
|
19
|
+
|
|
20
|
+
const { refModuleState, setModuleState: setModuleState_c } = useContext(context)
|
|
21
|
+
const getModuleState = useCallback(() => {
|
|
22
|
+
return refModuleState.current
|
|
23
|
+
}, [refModuleState])
|
|
24
|
+
|
|
25
|
+
const setModuleState = useCallback(
|
|
26
|
+
(newModuleState: ModuleState<S>) => {
|
|
27
|
+
refModuleState.current = newModuleState
|
|
28
|
+
setModuleState_c(newModuleState)
|
|
40
29
|
},
|
|
41
|
-
[
|
|
30
|
+
[refModuleState, setModuleState_c],
|
|
42
31
|
)
|
|
43
32
|
|
|
44
33
|
// 5. reducer.
|
|
45
34
|
const reduce = useCallback(
|
|
46
|
-
(action:
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
return
|
|
35
|
+
(action: BaseAction): ModuleState<S> => {
|
|
36
|
+
const moduleState = getModuleState()
|
|
37
|
+
const newModuleState = reducer(moduleState, action)
|
|
38
|
+
return newModuleState
|
|
50
39
|
},
|
|
51
|
-
[reducer,
|
|
40
|
+
[reducer, getModuleState],
|
|
52
41
|
)
|
|
53
42
|
|
|
54
|
-
// augmented
|
|
55
|
-
const
|
|
56
|
-
(action
|
|
43
|
+
// augmented setter.
|
|
44
|
+
const set: set<S> = useCallback(
|
|
45
|
+
(action) => {
|
|
57
46
|
if (typeof action === 'function') {
|
|
58
|
-
action
|
|
47
|
+
// action is Thunk<S, A>
|
|
48
|
+
action(set, getModuleState)
|
|
59
49
|
return
|
|
60
50
|
}
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
// action is not function. so action is BaseAction
|
|
53
|
+
const newModuleState = reduce(action)
|
|
54
|
+
setModuleState(newModuleState)
|
|
64
55
|
},
|
|
65
|
-
[
|
|
56
|
+
[getModuleState, setModuleState, reduce],
|
|
66
57
|
)
|
|
67
58
|
|
|
68
|
-
return [
|
|
59
|
+
return [refModuleState.current, set]
|
|
69
60
|
}
|
package/types/ThunkContext.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
2
|
type Props = {
|
|
3
|
-
|
|
4
|
-
children?:
|
|
3
|
+
modules?: string[];
|
|
4
|
+
children?: ReactNode;
|
|
5
5
|
};
|
|
6
|
-
declare const ThunkContext: (props: Props) =>
|
|
6
|
+
declare const ThunkContext: (props: Props) => ReactNode;
|
|
7
7
|
export default ThunkContext;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModuleState, State } from '../stateTypes';
|
|
2
|
+
import type { ActionOrThunk } from './ActionOrThunk';
|
|
3
|
+
import type BaseAction from './baseAction';
|
|
4
|
+
import type { Thunk } from './thunk';
|
|
5
|
+
export type { Thunk, ActionOrThunk, BaseAction };
|
|
6
|
+
export type ActionFunc<S extends State> = (...params: any[]) => ActionOrThunk<S>;
|
|
7
|
+
export type ThunkFunc<S extends State> = (...params: any[]) => Thunk<S>;
|
|
8
|
+
export type GetModuleState<S extends State> = () => ModuleState<S>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { State } from './stateTypes';
|
|
2
|
+
import type { ThunkModule } from './thunkModule';
|
|
3
|
+
declare const _default: <S extends State>(theDo: ThunkModule<S>) => void;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const registerThunk: <S extends State>(theDo: ThunkModule<S>) => void;
|
package/types/dispatch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Dispatch as rDispatch } from 'react';
|
|
2
|
-
import type { ActionOrThunk } from './action';
|
|
2
|
+
import type { ActionOrThunk } from './action/ActionOrThunk';
|
|
3
3
|
import type { State } from './stateTypes';
|
|
4
4
|
export type Dispatch<S extends State> = rDispatch<ActionOrThunk<S>>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Dispatch } from './dispatch';
|
|
2
2
|
import type { State } from './stateTypes';
|
|
3
|
-
import type { ThunkModule, ThunkModuleFunc } from './
|
|
4
|
-
import { type DefaultThunkModuleFuncMap } from './
|
|
5
|
-
import type { Thunk as rThunk } from './useThunkReducer';
|
|
3
|
+
import type { ThunkModule, ThunkModuleFunc } from './thunkModule';
|
|
4
|
+
import { type DefaultThunkModuleFuncMap } from './thunkModule/defaultThunkModuleFuncMap';
|
|
6
5
|
type VoidReturnType<T extends (...params: any[]) => unknown> = (...params: Parameters<T>) => void;
|
|
7
6
|
export type DispatchFuncMap<S extends State, T extends ThunkModuleFunc<S>> = {
|
|
8
7
|
[action in keyof T]: VoidReturnType<T[action]>;
|
|
@@ -14,5 +13,5 @@ export interface DispatchFuncMapByClassMap<S extends State, T extends ThunkModul
|
|
|
14
13
|
[className: string]: DispatchFuncMap<S, T>;
|
|
15
14
|
}
|
|
16
15
|
export declare const DISPATCH_FUNC_MAP_BY_CLASS_MAP: DispatchFuncMapByClassMap<any, any>;
|
|
17
|
-
export declare const constructDispatchMap: <S extends State, T extends ThunkModuleFunc<S
|
|
16
|
+
export declare const constructDispatchMap: <S extends State, T extends ThunkModuleFunc<S>>(theDo: ThunkModule<S>, dispatch: Dispatch<S>, dispatchMap: DispatchFuncMap<S, T>) => DispatchFuncMap<S, T>;
|
|
18
17
|
export {};
|