@chhsiao1981/use-thunk 10.4.0 → 12.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.
Files changed (88) hide show
  1. package/README.md +63 -59
  2. package/dist/ThunkContext.d.ts +7 -0
  3. package/dist/createReducer.d.ts +4 -0
  4. package/dist/createThunk.d.ts +4 -0
  5. package/dist/dispatch.d.ts +4 -0
  6. package/dist/dispatchFuncMap.d.ts +18 -0
  7. package/dist/genUUID.d.ts +1 -0
  8. package/dist/index.d.ts +15 -0
  9. package/{types → dist}/init.d.ts +0 -3
  10. package/dist/reduceMap.d.ts +6 -0
  11. package/dist/reducer.d.ts +5 -0
  12. package/dist/remove.d.ts +5 -0
  13. package/dist/setDefaultID.d.ts +5 -0
  14. package/dist/stateTypes.d.ts +16 -0
  15. package/dist/states.d.ts +9 -0
  16. package/{types → dist}/thunk.d.ts +6 -3
  17. package/dist/thunkContextMap.d.ts +15 -0
  18. package/dist/thunkContextTypes.d.ts +8 -0
  19. package/{types → dist}/thunkModuleFuncMap.d.ts +1 -0
  20. package/dist/update.d.ts +6 -0
  21. package/dist/useThunk.d.ts +12 -0
  22. package/dist/useThunkReducer.d.ts +17 -0
  23. package/package.json +1 -1
  24. package/src/ThunkContext.tsx +17 -17
  25. package/src/action/ActionOrThunk.ts +5 -0
  26. package/src/action/baseAction.ts +6 -0
  27. package/src/action/index.ts +16 -0
  28. package/src/action/thunk.ts +9 -0
  29. package/src/createReducer.ts +7 -7
  30. package/src/createThunk.ts +24 -0
  31. package/src/get.ts +3 -0
  32. package/src/index.ts +20 -30
  33. package/src/init/index.ts +26 -0
  34. package/src/init/initCore.ts +31 -0
  35. package/src/reduceMap.ts +3 -4
  36. package/src/reducer.ts +4 -4
  37. package/src/remove.ts +10 -25
  38. package/src/set.ts +7 -0
  39. package/src/setDefaultID.ts +5 -5
  40. package/src/setMap.ts +65 -0
  41. package/src/stateTypes.ts +3 -3
  42. package/src/states.ts +21 -18
  43. package/src/thunkContextMap.ts +4 -4
  44. package/src/thunkContextTypes.ts +4 -4
  45. package/src/thunkModule/defaultThunkModuleFuncMap.ts +15 -0
  46. package/src/thunkModule/index.ts +20 -0
  47. package/src/update.ts +26 -0
  48. package/src/useThunk.ts +23 -44
  49. package/src/useThunkReducer.ts +41 -42
  50. package/types/ThunkContext.d.ts +4 -4
  51. package/types/action/ActionOrThunk.d.ts +4 -0
  52. package/types/action/baseAction.d.ts +5 -0
  53. package/types/action/index.d.ts +8 -0
  54. package/types/action/thunk.d.ts +3 -0
  55. package/types/createThunk.d.ts +4 -0
  56. package/types/dispatch.d.ts +1 -1
  57. package/types/dispatchFuncMap.d.ts +4 -5
  58. package/types/get.d.ts +2 -0
  59. package/types/index.d.ts +10 -9
  60. package/types/init/index.d.ts +7 -0
  61. package/types/init/initCore.d.ts +9 -0
  62. package/types/reducer.d.ts +4 -4
  63. package/types/remove.d.ts +4 -4
  64. package/types/set.d.ts +4 -0
  65. package/types/setDefaultID.d.ts +3 -3
  66. package/types/setMap.d.ts +17 -0
  67. package/types/stateTypes.d.ts +2 -2
  68. package/types/states.d.ts +8 -8
  69. package/types/thunkContextMap.d.ts +4 -4
  70. package/types/thunkContextTypes.d.ts +4 -4
  71. package/types/thunkModule/defaultThunkModuleFuncMap.d.ts +5 -0
  72. package/types/thunkModule/index.d.ts +15 -0
  73. package/types/update.d.ts +5 -0
  74. package/types/useThunk.d.ts +5 -8
  75. package/types/useThunkReducer.d.ts +5 -11
  76. package/dist/index.js +0 -1723
  77. package/dist/index.umd.cjs +0 -50
  78. package/src/action.ts +0 -20
  79. package/src/dispatch.ts +0 -6
  80. package/src/dispatchFuncMap.ts +0 -67
  81. package/src/init.ts +0 -64
  82. package/src/registerThunk.ts +0 -42
  83. package/src/setData.ts +0 -26
  84. package/src/thunk.ts +0 -20
  85. package/src/thunkModuleFuncMap.ts +0 -11
  86. package/types/registerThunk.d.ts +0 -4
  87. package/types/setData.d.ts +0 -5
  88. /package/{types → dist}/action.d.ts +0 -0
@@ -0,0 +1,24 @@
1
+ import { createContext, type Dispatch, type SetStateAction } from 'react'
2
+ import type { ModuleState, State } from './stateTypes'
3
+ import { THUNK_CONTEXT_MAP } from './thunkContextMap'
4
+ import type { ThunkModule } from './thunkModule'
5
+
6
+ export default <S extends State>(theDo: ThunkModule<S>) => {
7
+ const { name, defaultState } = theDo
8
+
9
+ if (THUNK_CONTEXT_MAP.theMap[name]) {
10
+ console.warn('createThunk: already init:', name)
11
+ return
12
+ }
13
+
14
+ const moduleState: ModuleState<S> = { name, nodes: {}, defaultState }
15
+ const setModuleState: Dispatch<SetStateAction<ModuleState<S>>> = () => {}
16
+ const refModuleState = { current: moduleState }
17
+ const context = createContext({ refModuleState: refModuleState, setModuleState })
18
+
19
+ THUNK_CONTEXT_MAP.theMap[name] = { context, refModuleState }
20
+ const theList = Object.keys(THUNK_CONTEXT_MAP.theMap).sort()
21
+ THUNK_CONTEXT_MAP.theList = theList
22
+
23
+ console.info('createThunk: done:', name)
24
+ }
package/src/get.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { State } from './stateTypes'
2
+
3
+ export type get = <S extends State>(id: string) => S
package/src/index.ts CHANGED
@@ -1,52 +1,42 @@
1
- import type { GetClassState, Thunk } from './action'
2
- import type { Dispatch } from './dispatch'
3
- import type { DispatchFuncMap } from './dispatchFuncMap'
1
+ import type { GetModuleState, Thunk } from './action'
2
+ import createThunk from './createThunk'
4
3
  import { genUUID } from './genUUID'
4
+ import type { get } from './get'
5
5
  import { type InitParams, init } from './init'
6
- import registerThunk from './registerThunk'
7
6
  import { remove } from './remove'
8
- import { setData } from './setData'
7
+ import type { set } from './set'
9
8
  import { setDefaultID } from './setDefaultID'
10
- import { getDefaultID, getNode, getState, mustGetState, mustGetStateByThunk } from './states'
11
- import type { ClassState, NodeState, NodeStateMap, State } from './stateTypes'
9
+ import type { setMap } from './setMap'
10
+ import { getDefaultID, getNode, getState, getStateByModule, getStateOrNullByModule } from './states'
11
+ import type { ModuleState, State } from './stateTypes'
12
12
  import ThunkContext from './ThunkContext'
13
- import type { ThunkModule, ThunkModuleToFunc } from './thunk'
13
+ import type { ThunkModule, ThunkModuleToFunc } from './thunkModule'
14
+ import { update } from './update'
14
15
  import useThunk, { type UseThunk } from './useThunk'
15
16
 
16
17
  export {
17
- registerThunk,
18
+ createThunk,
18
19
  useThunk,
19
- ThunkContext,
20
20
  type UseThunk,
21
+ ThunkContext,
21
22
  type State,
22
- type NodeState,
23
- type NodeStateMap,
24
- // type NodeStateMapByClass, // XXX for global state
25
- type ClassState,
26
- type GetClassState,
27
- // type BaseAction, // XXX deemphasize action
23
+ type ModuleState,
24
+ type GetModuleState,
28
25
  type Thunk,
29
- // type ActionOrThunk, // XXX deemphasize action
30
- // type ActionFunc, // XXX deemphasize action
31
- // type Reducer, // XXX deemphasize reducer
32
26
  type ThunkModule,
33
27
  type ThunkModuleToFunc,
34
- // type ReduceFunc, // XXX deemphasize reducer
35
- type Dispatch,
36
- type DispatchFuncMap,
37
- // type DefaultDispatchFuncMap, // XXX deemphasize default
38
- getDefaultID,
28
+ type set,
29
+ type setMap,
30
+ type get,
39
31
  getNode,
32
+ getDefaultID,
33
+ getStateOrNullByModule,
34
+ getStateByModule,
40
35
  getState,
41
- mustGetState,
42
- mustGetStateByThunk,
43
36
  init,
44
37
  type InitParams,
45
- setData,
38
+ update,
46
39
  remove,
47
- // type DefaultThunkModuleFuncMap as DefaultReducerModuleFuncMap, // XXX deemphasize default
48
- // type ReduceMap, // XXX deemphasize reducer
49
- // createReducer, // XXX deemphasize reducer
50
40
  setDefaultID,
51
41
  genUUID,
52
42
  }
@@ -0,0 +1,26 @@
1
+ import type { Thunk } from '../action'
2
+ import { genUUID } from '../genUUID'
3
+ import { setDefaultID } from '../setDefaultID'
4
+ import type { State } from '../stateTypes'
5
+ import initCore from './initCore'
6
+
7
+ // InitParams
8
+ export interface InitParams<S extends State> {
9
+ myID?: string
10
+ state: S
11
+ }
12
+
13
+ export const init = <S extends State>(params: InitParams<S>, myuuidv4?: () => string): Thunk<S> => {
14
+ return (set, _, getModuleState) => {
15
+ const myID = params.myID ?? genUUID(myuuidv4)
16
+
17
+ const { state } = params
18
+ set(initCore(myID, state))
19
+
20
+ const { defaultID } = getModuleState()
21
+
22
+ if (!defaultID) {
23
+ set(setDefaultID(myID))
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,31 @@
1
+ import type BaseAction from '../action/baseAction'
2
+ import type { ModuleState, NodeState, NodeStateMap, State } from '../stateTypes'
3
+
4
+ export interface InitAction<S extends State> extends BaseAction {
5
+ state: S
6
+ }
7
+
8
+ export const INIT = '@chhsiao1981/use-thunk/INIT'
9
+ export default <S extends State>(myID: string, state: S): InitAction<S> => {
10
+ return {
11
+ myID,
12
+ type: INIT,
13
+ state,
14
+ }
15
+ }
16
+
17
+ export const reduceInit = <S extends State>(
18
+ moduleState: ModuleState<S>,
19
+ action: BaseAction,
20
+ ): ModuleState<S> => {
21
+ const { myID, state } = action as InitAction<S>
22
+
23
+ const myNode: NodeState<S> = {
24
+ id: myID,
25
+ state: state,
26
+ }
27
+ const newNodes: NodeStateMap<S> = Object.assign({}, moduleState.nodes, { [myID]: myNode })
28
+ const newModuleState: ModuleState<S> = Object.assign({}, moduleState, { nodes: newNodes })
29
+
30
+ return newModuleState
31
+ }
package/src/reduceMap.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { INIT, reduceInit } from './init'
1
+ import { INIT, reduceInit } from './init/initCore'
2
2
  import type { ReduceFunc } from './reducer'
3
3
  import { REMOVE, reduceRemove } from './remove'
4
- import { reduceSetData, SET_DATA } from './setData'
5
4
  import { reduceSetDefaultID, SET_DEFAULT_ID } from './setDefaultID'
6
5
  import type { State } from './stateTypes'
6
+ import { reduceUpdate, UPDATE } from './update'
7
7
 
8
8
  export interface ReduceMap<S extends State> {
9
9
  [type: string]: ReduceFunc<S>
@@ -11,9 +11,8 @@ export interface ReduceMap<S extends State> {
11
11
 
12
12
  // default reduceMap
13
13
  export const DEFAULT_REDUCE_MAP: <S extends State>() => ReduceMap<S> = () => ({
14
- // @ts-expect-error baseAction in ReduceMap
15
14
  [INIT]: reduceInit,
16
- [SET_DATA]: reduceSetData,
15
+ [UPDATE]: reduceUpdate,
17
16
  [REMOVE]: reduceRemove,
18
17
 
19
18
  // setDefaultID.
package/src/reducer.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { Reducer as rReducer } from 'react'
2
- import type { BaseAction } from './action'
3
- import type { ClassState, State } from './stateTypes'
2
+ import type BaseAction from './action/baseAction'
3
+ import type { ModuleState, State } from './stateTypes'
4
4
 
5
5
  // Reducer
6
- export type Reducer<S extends State> = rReducer<ClassState<S>, BaseAction>
6
+ export type Reducer<S extends State> = rReducer<ModuleState<S>, BaseAction>
7
7
 
8
8
  // ReduceFunc
9
- export type ReduceFunc<S extends State> = (state: ClassState<S>, action: BaseAction) => ClassState<S>
9
+ export type ReduceFunc<S extends State> = (state: ModuleState<S>, action: BaseAction) => ModuleState<S>
package/src/remove.ts CHANGED
@@ -1,47 +1,32 @@
1
- import type { BaseAction, Thunk } from './action'
2
- import type { ClassState, NodeStateMap, State } from './stateTypes'
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 removeCore = (myID: string): BaseAction => ({
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
- classState: ClassState<S>,
11
+ moduleState: ModuleState<S>,
27
12
  action: BaseAction,
28
- ): ClassState<S> => {
13
+ ): ModuleState<S> => {
29
14
  const { myID } = action
30
15
 
31
- const myNode = classState.nodes[myID]
16
+ const myNode = moduleState.nodes[myID]
32
17
  if (!myNode) {
33
- return classState
18
+ return moduleState
34
19
  }
35
20
 
36
- const newNodes = Object.keys(classState.nodes)
21
+ const newNodes = Object.keys(moduleState.nodes)
37
22
  .filter((each) => each !== myID)
38
23
  .reduce((r: NodeStateMap<S>, x) => {
39
- r[x] = classState.nodes[x]
24
+ r[x] = moduleState.nodes[x]
40
25
  return r
41
26
  }, {})
42
27
 
43
28
  // defaultID
44
- const newState = Object.assign({}, classState, { nodes: newNodes })
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>>
@@ -1,5 +1,5 @@
1
- import type { BaseAction } from './action'
2
- import type { ClassState, State } from './stateTypes'
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
- classState: ClassState<S>,
11
+ moduleState: ModuleState<S>,
12
12
  action: BaseAction,
13
- ): ClassState<S> => {
13
+ ): ModuleState<S> => {
14
14
  const { myID } = action
15
15
 
16
- return Object.assign({}, classState, { defaultID: myID })
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,9 @@ export type NodeStateMap<S extends State> = {
13
13
  [key: string]: NodeState<S>
14
14
  }
15
15
 
16
- // ClassState
17
- export type ClassState<S extends State> = {
18
- myClass: string
16
+ // ModuleState
17
+ export type ModuleState<S extends State> = {
18
+ name: string
19
19
  defaultID?: string | null
20
20
  nodes: NodeStateMap<S>
21
21
  defaultState: S
package/src/states.ts CHANGED
@@ -1,47 +1,50 @@
1
- import type { DispatchFuncMap } from './dispatchFuncMap'
2
- import type { ClassState, NodeState, State } from './stateTypes'
3
- import type { ThunkModuleFunc } from './thunk'
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>(classState: ClassState<S>): string => {
7
- return classState.defaultID ?? ''
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
- classState: ClassState<S>,
11
+ moduleState: ModuleState<S>,
12
12
  myID?: string,
13
13
  ): NodeState<S> | null => {
14
- const theID = myID ? myID : getDefaultID(classState)
14
+ const theID = myID ? myID : getDefaultID(moduleState)
15
15
  if (!theID) {
16
16
  return null
17
17
  }
18
18
 
19
- return classState.nodes[theID] || null
19
+ return moduleState.nodes[theID] || null
20
20
  }
21
21
 
22
- export const getState = <S extends State>(classState: ClassState<S>, myID?: string): S | null => {
23
- const theID = myID ? myID : getDefaultID(classState)
22
+ export const getStateOrNullByModule = <S extends State>(
23
+ moduleState: ModuleState<S>,
24
+ myID?: string,
25
+ ): S | null => {
26
+ const theID = myID ? myID : getDefaultID(moduleState)
24
27
  if (!theID) {
25
28
  return null
26
29
  }
27
30
 
28
- const me = classState.nodes[theID]
31
+ const me = moduleState.nodes[theID]
29
32
  if (!me) {
30
33
  return null
31
34
  }
32
35
  return me.state
33
36
  }
34
37
 
35
- export const mustGetState = <S extends State>(classState: ClassState<S>, myID?: string): S => {
36
- return getState(classState, myID) || classState.defaultState
38
+ export const getStateByModule = <S extends State>(moduleState: ModuleState<S>, myID?: string): S => {
39
+ return getStateOrNullByModule(moduleState, myID) || moduleState.defaultState
37
40
  }
38
41
 
39
- export const mustGetStateByThunk = <S extends State, R extends ThunkModuleFunc<S>>(
42
+ export const getState = <S extends State, R extends ThunkModuleFunc<S>>(
40
43
  theUseThunk: UseThunk<S, R>,
41
44
  myID?: string,
42
- ): [S, DispatchFuncMap<S, R>, string] => {
43
- const [classState, theDo] = theUseThunk
44
- const theID = myID ? myID : getDefaultID(classState)
45
- const state = mustGetState(classState, theID)
45
+ ): [S, setMap<S, R>, string] => {
46
+ const [moduleState, theDo] = theUseThunk
47
+ const theID = myID ? myID : getDefaultID(moduleState)
48
+ const state = getStateByModule(moduleState, theID)
46
49
  return [state, theDo, theID]
47
50
  }
@@ -1,16 +1,16 @@
1
1
  import type { Context as rContext } from 'react'
2
- import type { ClassState } from './stateTypes'
2
+ import type { ModuleState } from './stateTypes'
3
3
  import type { Context } from './thunkContextTypes'
4
4
 
5
5
  export type ThunkContextMap = {
6
6
  theMap: {
7
- [classname: string]: {
7
+ [moduleName: string]: {
8
8
  // biome-ignore lint/suspicious/noExplicitAny: ThunkContextMap can be any type
9
9
  context: rContext<Context<any>>
10
10
 
11
- // we need to use refClassState to sync all the classState in all ops.
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
- refClassState: { current: ClassState<any> }
13
+ refModuleState: { current: ModuleState<any> }
14
14
  }
15
15
  }
16
16
  theList: string[]
@@ -1,8 +1,8 @@
1
1
  import type { Dispatch, SetStateAction } from 'react'
2
- import type { ClassState, State } from './stateTypes'
2
+ import type { ModuleState, State } from './stateTypes'
3
3
 
4
4
  export type Context<S extends State> = {
5
- // INFO: we use refClassState to reference across all the useThunk of the same class in different ops.
6
- refClassState: { current: ClassState<S> }
7
- setClassState: Dispatch<SetStateAction<ClassState<S>>>
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,15 @@
1
+ import type { ActionFunc } from '../action'
2
+ import { init } from '../init'
3
+ import { remove } from '../remove'
4
+ import { update } from '../update'
5
+
6
+ export const DEFAULT_THUNK_MODULE_FUNC_MAP: DefaultThunkModuleFuncMap = {
7
+ init,
8
+ update,
9
+ remove,
10
+ }
11
+
12
+ export type DefaultThunkModuleFuncMap = {
13
+ // biome-ignore lint/suspicious/noExplicitAny: DefaultThunkModuleFuncMap can be any type.
14
+ [action: string]: ActionFunc<any>
15
+ }
@@ -0,0 +1,20 @@
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
+ default?: Reducer<S>
17
+ defaultState: S
18
+ } & ThunkModuleBase<S>
19
+
20
+ export type ThunkModuleToFunc<T> = Omit<T, 'name' | 'default' | 'defaultState'>
package/src/update.ts ADDED
@@ -0,0 +1,26 @@
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 reduceUpdate = <S extends State>(
12
+ moduleState: ModuleState<S>,
13
+ action: BaseAction,
14
+ ): ModuleState<S> => {
15
+ const { myID, data } = action
16
+
17
+ const myNode = moduleState.nodes[myID]
18
+ if (!myNode) return moduleState
19
+
20
+ const newMyState = Object.assign({}, myNode.state, data)
21
+ const newMyNode = Object.assign({}, myNode, { state: newMyState })
22
+ const newNodes = Object.assign({}, moduleState.nodes, { [myID]: newMyNode })
23
+ const newModuleState = Object.assign({}, moduleState, { nodes: newNodes })
24
+
25
+ return newModuleState
26
+ }
package/src/useThunk.ts CHANGED
@@ -1,21 +1,14 @@
1
1
  import { useMemo } from 'react'
2
2
  import { createReducer } from './createReducer'
3
- import {
4
- constructDispatchMap,
5
- type DispatchFuncMap,
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: DISPACH_MAP_BY_CLASS can by any type
13
- const DISPACH_MAP_BY_CLASS: DispatchFuncMapByClassMap<any, any> = {}
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
@@ -23,49 +16,35 @@ export type UseThunk<S extends State, R extends ThunkModuleFunc<S>> = [
23
16
  export default <S extends State, R extends ThunkModuleFunc<S>>(
24
17
  theDo: ThunkModule<S>,
25
18
  ): UseThunk<S, R> => {
26
- const { myClass } = theDo
19
+ const { name } = theDo
27
20
 
28
- // 1. dispatchMapByClass
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]
21
+ // 1. It requires shared nodes for the same module to have the same setMap.
22
+ const isFirstTime = !SET_MAP_BY_MODULE[name]
37
23
  if (isFirstTime) {
38
- // @ts-expect-error init dispatchMap
39
- dispatchMapByClass[myClass] = {}
24
+ SET_MAP_BY_MODULE[name] = {}
40
25
  }
41
- const dispatchMap = dispatchMapByClass[myClass]
26
+ const setMap = SET_MAP_BY_MODULE[name] as setMap<S, R>
42
27
 
43
- // 4. reducer.
44
- // using useState to have theDo.default as optional.
45
- // theReducer won't be changed.
46
- //
47
- // theReducer is different for different reducers,
48
- // even within the same class.
49
- // However, because theReducer is a pure function
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>(), [])
28
+ // 2. reducer.
29
+ // theReducer is different for different useThunk,
30
+ // even within the same module.
31
+ // However, because theReducer is a pure function by
32
+ // having ModuleState as the input. It is ok to have
33
+ // different reducers within the same module.
34
+ const theReducer = useMemo(() => createReducer<S>(), [])
55
35
 
56
- // 5. useThunkReducer
57
- const [classState, dispatch] = useThunkReducer(theReducer, myClass)
36
+ // 3. useThunkReducer
37
+ const [moduleState, set] = useThunkReducer(theReducer, name)
58
38
 
59
- // INFO useMemo is to avoid accidental included in useEffect.
60
39
  const ret: UseThunk<S, R> = useMemo(() => {
61
- return [classState, dispatchMap]
62
- }, [classState, dispatchMap])
40
+ return [moduleState, setMap]
41
+ }, [moduleState, setMap])
63
42
 
64
43
  if (!isFirstTime) {
65
44
  return ret
66
45
  }
67
46
 
68
- constructDispatchMap(theDo, dispatch, dispatchMap)
47
+ constructSetMap(theDo, set, setMap)
69
48
 
70
49
  return ret
71
50
  }