@chhsiao1981/use-thunk 10.3.0 → 10.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chhsiao1981/use-thunk",
3
- "version": "10.3.0",
3
+ "version": "10.4.0",
4
4
  "type": "module",
5
5
  "description": "A framework easily using useThunk to manage the data-state.",
6
6
  "homepage": "https://github.com/chhsiao1981/use-thunk",
@@ -56,7 +56,7 @@
56
56
  "vite": "^6.4.1",
57
57
  "vitest": "^4.1.0"
58
58
  },
59
- "dependencies": {
59
+ "peerDependencies": {
60
60
  "react": ">=18.3.1",
61
61
  "uuid": "^14.0.0"
62
62
  }
@@ -1,28 +1,31 @@
1
- import { type JSX, useMemo, useState } from 'react'
1
+ import { type ReactNode, useMemo, useState } from 'react'
2
2
  import { THUNK_CONTEXT_MAP } from './thunkContextMap'
3
3
 
4
4
  type Props = {
5
5
  classes?: string[]
6
- children?: JSX.Element | JSX.Element[]
6
+ children?: ReactNode
7
7
  }
8
- const ThunkContext = (props: Props): JSX.Element => {
9
- let { classes, children } = props
10
- if (!classes) {
11
- classes = THUNK_CONTEXT_MAP.theList
12
- }
8
+
9
+ const ThunkContext = (props: Props): ReactNode => {
10
+ const { classes: propsClasses, children } = props
11
+ const classes = propsClasses || THUNK_CONTEXT_MAP.theList
12
+ // 0. if there is no Thunk classes (no registerThunk): return children.
13
13
  if (classes.length === 0) {
14
- // @ts-expect-error with children
15
14
  return children
16
15
  }
17
16
 
17
+ // render the 0th class.
18
18
  const theClass = classes[0]
19
19
 
20
+ // 1. get the context and classState from context map.
20
21
  const { context: Context_m, refClassState } = THUNK_CONTEXT_MAP.theMap[theClass]
21
22
 
23
+ // 2. setup classState.
22
24
  // biome-ignore lint/correctness/useHookAtTopLevel: the order is fixed.
23
25
  const [classState, setClassState] = useState(refClassState.current)
24
-
25
26
  refClassState.current = classState
27
+
28
+ // 3. value reset only if classState is changed.
26
29
  // biome-ignore lint/correctness/useHookAtTopLevel: the order is fixed.
27
30
  const value = useMemo(
28
31
  () => ({
@@ -32,9 +35,11 @@ const ThunkContext = (props: Props): JSX.Element => {
32
35
  [classState],
33
36
  )
34
37
 
38
+ // 4. get theChildren
35
39
  const theChildren =
36
40
  classes.length === 1 ? children : ThunkContext({ classes: classes.slice(1), children })
37
41
 
42
+ // 5. return context.
38
43
  return <Context_m.Provider value={value}>{theChildren}</Context_m.Provider>
39
44
  }
40
45
 
@@ -27,7 +27,7 @@ export const constructDispatchMap = <
27
27
  T extends ThunkModuleFunc<S>,
28
28
  A extends BaseAction,
29
29
  >(
30
- theDo: ThunkModule<S, T>,
30
+ theDo: ThunkModule<S>,
31
31
  dispatch: (action: A | rThunk<S, A>) => void,
32
32
  dispatchMap: DispatchFuncMap<S, T>,
33
33
  ) => {
@@ -40,7 +40,8 @@ export const constructDispatchMap = <
40
40
  return val
41
41
  }
42
42
 
43
- const action: ActionFunc<S> = theDo[eachAction]
43
+ // because action is a function.
44
+ const action = theDo[eachAction] as ActionFunc<S>
44
45
 
45
46
  // @ts-expect-error eachAction is in DispatchFuncMap<S, R>
46
47
  // biome-ignore lint/suspicious/noExplicitAny: action parameters can be any types.
@@ -1,17 +1,18 @@
1
1
  import { createContext, type Dispatch, type SetStateAction } from 'react'
2
2
  import type { ClassState, State } from './stateTypes'
3
- import type { ThunkModule, ThunkModuleFunc } from './thunk'
3
+ import type { ThunkModule } from './thunk'
4
4
  import { THUNK_CONTEXT_MAP } from './thunkContextMap'
5
5
 
6
- export default <S extends State, R extends ThunkModuleFunc<S>>(theDo: ThunkModule<S, R>) => {
6
+ export default <S extends State>(theDo: ThunkModule<S>) => {
7
7
  const { myClass, defaultState } = theDo
8
8
 
9
9
  if (THUNK_CONTEXT_MAP.theMap[myClass]) {
10
- // already init
11
- console.info('regsterThunk: already init:', myClass)
10
+ // 1. already init
11
+ console.warn('regsterThunk: already init:', myClass)
12
12
  return
13
13
  }
14
14
 
15
+ // 2. to initialize classState, setClassState, and refClassState.
15
16
  const classState: ClassState<S> = {
16
17
  myClass,
17
18
  nodes: {},
@@ -19,15 +20,20 @@ export default <S extends State, R extends ThunkModuleFunc<S>>(theDo: ThunkModul
19
20
  }
20
21
  const setClassState: Dispatch<SetStateAction<ClassState<S>>> = () => {}
21
22
  const refClassState = { current: classState }
23
+
24
+ // 3. create context
22
25
  const context = createContext({
23
26
  refClassState,
24
27
  setClassState,
25
28
  })
26
29
 
30
+ // 4. setup THUNK_CONTEXT_MAP.theMap.
27
31
  THUNK_CONTEXT_MAP.theMap[myClass] = {
28
32
  context,
29
33
  refClassState,
30
34
  }
35
+
36
+ // 5. setup THUNK_CONTEXT_MAP.theList, to ensure the rendering order.
31
37
  const theList = Object.keys(THUNK_CONTEXT_MAP.theMap)
32
38
  theList.sort()
33
39
  THUNK_CONTEXT_MAP.theList = theList
package/src/thunk.ts CHANGED
@@ -2,15 +2,19 @@ import type { ActionFunc } from './action'
2
2
  import type { Reducer } from './reducer'
3
3
  import type { State } from './stateTypes'
4
4
 
5
- export interface ThunkModuleFunc<S extends State> {
5
+ export interface ThunkModuleBase<S extends State> {
6
+ [idx: string]: ActionFunc<S> | string | Reducer<S> | S | undefined
7
+ }
8
+
9
+ export interface ThunkModuleFunc<S extends State> extends ThunkModuleBase<S> {
6
10
  [action: string]: ActionFunc<S>
7
11
  }
8
12
 
9
13
  // This is used as the parameter for useThunk.
10
- export type ThunkModule<S extends State, T extends ThunkModuleFunc<S>> = {
14
+ export type ThunkModule<S extends State> = {
11
15
  myClass: string
12
16
  default?: Reducer<S>
13
17
  defaultState: S
14
- } & T
18
+ } & ThunkModuleBase<S>
15
19
 
16
20
  export type ThunkModuleToFunc<T> = Omit<T, 'myClass' | 'default' | 'defaultState'>
@@ -8,7 +8,7 @@ export type ThunkContextMap = {
8
8
  // biome-ignore lint/suspicious/noExplicitAny: ThunkContextMap can be any type
9
9
  context: rContext<Context<any>>
10
10
 
11
- // INFO We need to use refClassState to sync all the classState in all ops.
11
+ // we need to use refClassState to sync all the classState in all ops.
12
12
  // biome-ignore lint/suspicious/noExplicitAny: ThunkContextMap can be any type
13
13
  refClassState: { current: ClassState<any> }
14
14
  }
package/src/useThunk.ts CHANGED
@@ -21,7 +21,7 @@ export type UseThunk<S extends State, R extends ThunkModuleFunc<S>> = [
21
21
  * useThunk
22
22
  **********/
23
23
  export default <S extends State, R extends ThunkModuleFunc<S>>(
24
- theDo: ThunkModule<S, R>,
24
+ theDo: ThunkModule<S>,
25
25
  ): UseThunk<S, R> => {
26
26
  const { myClass } = theDo
27
27
 
@@ -55,10 +55,12 @@ export default <S extends State, A extends BaseAction>(
55
55
  const dispatch = useCallback(
56
56
  (action: A | Thunk<S, A>) => {
57
57
  if (typeof action === 'function') {
58
+ // action is Thunk<S, A>
58
59
  action(dispatch, getClassState)
59
60
  return
60
61
  }
61
62
 
63
+ // action is not function. so action is A
62
64
  const newClassState = reduce(action)
63
65
  setClassState(newClassState)
64
66
  },