Skip to content

Commit 282b5dc

Browse files
feat(overmind-react): new granular hooks
1 parent 963586b commit 282b5dc

File tree

1 file changed

+146
-120
lines changed
  • packages/node_modules/overmind-react/src

1 file changed

+146
-120
lines changed

packages/node_modules/overmind-react/src/index.ts

Lines changed: 146 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -53,156 +53,182 @@ export const Provider: React.ProviderExoticComponent<
5353
React.ProviderProps<Overmind<IConfiguration> | OvermindMock<IConfiguration>>
5454
> = context.Provider
5555

56-
export const createHook = <Config extends IConfiguration>(): (() => {
57-
state: Overmind<Config>['state']
58-
actions: Overmind<Config>['actions']
59-
effects: Overmind<Config>['effects']
60-
addMutationListener: (cb: IMutationCallback) => () => void
61-
reaction: Overmind<Config>['reaction']
62-
}) => {
63-
let currentComponentInstanceId = 0
64-
const {
65-
ReactCurrentOwner,
66-
} = (react as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
67-
const useCurrentComponent = () => {
68-
return ReactCurrentOwner &&
69-
ReactCurrentOwner.current &&
70-
ReactCurrentOwner.current.elementType
71-
? ReactCurrentOwner.current.elementType
72-
: {}
73-
}
74-
const useForceRerender = () => {
75-
const [flushId, setState] = react.useState(() => -1)
76-
// We use memo here, instead of ref, to support fast-refresh
77-
const mountedRef = react.useMemo(() => ({ current: true}), [])
78-
79-
react.useEffect(
80-
() => () => {
81-
mountedRef.current = false
82-
},
83-
[]
84-
)
56+
const useForceRerender = () => {
57+
const [flushId, setState] = react.useState(() => -1)
58+
// We use memo here, instead of ref, to support fast-refresh
59+
const mountedRef = react.useMemo(() => ({ current: true}), [])
60+
61+
react.useEffect(
62+
() => () => {
63+
mountedRef.current = false
64+
},
65+
[]
66+
)
8567

86-
const forceRerender = (_, __, flushId): void => {
87-
if (mountedRef.current) {
88-
setState(flushId)
89-
}
90-
}
91-
return {
92-
forceRerender,
93-
flushId,
68+
const forceRerender = (_, __, flushId): void => {
69+
if (mountedRef.current) {
70+
setState(flushId)
9471
}
9572
}
73+
return {
74+
forceRerender,
75+
flushId,
76+
}
77+
}
9678

97-
return () => {
98-
const overmind = react.useContext(context) as Overmind<Config>
79+
let currentComponentInstanceId = 0
80+
const {
81+
ReactCurrentOwner,
82+
} = (react as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
83+
const useCurrentComponent = () => {
84+
return ReactCurrentOwner &&
85+
ReactCurrentOwner.current &&
86+
ReactCurrentOwner.current.elementType
87+
? ReactCurrentOwner.current.elementType
88+
: {}
89+
}
9990

100-
if (!(overmind as any).mode) {
101-
throwMissingContextError()
102-
}
91+
const useState = <Config extends IConfiguration>(): Overmind<Config>['state'] => {
92+
const overmind = react.useContext(context) as Overmind<Config>
10393

104-
if (isNode || (overmind as any).mode.mode === MODE_SSR) {
105-
return {
106-
state: overmind.state,
107-
actions: overmind.actions,
108-
effects: overmind.effects,
109-
addMutationListener: overmind.addMutationListener,
110-
reaction: overmind.reaction,
111-
}
112-
}
94+
if (!(overmind as any).mode) {
95+
throwMissingContextError()
96+
}
11397

114-
const tree = react.useMemo<any>(() =>
115-
(overmind as any).proxyStateTree.getTrackStateTree(), []
116-
)
98+
if (isNode || (overmind as any).mode.mode === MODE_SSR) {
99+
return overmind.state
100+
}
117101

118-
if (IS_PRODUCTION) {
119-
const { forceRerender } = useForceRerender()
102+
const tree = react.useMemo<any>(() =>
103+
(overmind as any).proxyStateTree.getTrackStateTree(), []
104+
)
120105

121-
react.useEffect(
122-
() => () => {
123-
;(overmind as any).proxyStateTree.disposeTree(tree)
124-
},
125-
[]
126-
)
106+
if (IS_PRODUCTION) {
107+
const { forceRerender } = useForceRerender()
127108

128-
react.useLayoutEffect(() => tree.stopTracking())
109+
react.useEffect(
110+
() => () => {
111+
;(overmind as any).proxyStateTree.disposeTree(tree)
112+
},
113+
[]
114+
)
129115

130-
tree.track(forceRerender)
131-
} else {
132-
const component = useCurrentComponent()
133-
const name = component.name
134-
component.__componentId =
135-
typeof component.__componentId === 'undefined'
136-
? nextComponentId++
137-
: component.__componentId
116+
react.useLayoutEffect(() => tree.stopTracking())
138117

139-
const { current: componentInstanceId } = react.useRef<any>(
140-
currentComponentInstanceId++
141-
)
118+
tree.track(forceRerender)
119+
} else {
120+
const component = useCurrentComponent()
121+
const name = component.name
122+
component.__componentId =
123+
typeof component.__componentId === 'undefined'
124+
? nextComponentId++
125+
: component.__componentId
142126

143-
const { flushId, forceRerender } = useForceRerender()
127+
const { current: componentInstanceId } = react.useRef<any>(
128+
currentComponentInstanceId++
129+
)
144130

145-
react.useLayoutEffect(() => {
146-
overmind.eventHub.emitAsync(EventType.COMPONENT_ADD, {
147-
componentId: component.__componentId,
148-
componentInstanceId,
149-
name,
150-
paths: Array.from(tree.pathDependencies) as any,
151-
})
131+
const { flushId, forceRerender } = useForceRerender()
152132

153-
return () => {
154-
;(overmind as any).proxyStateTree.disposeTree(tree)
155-
overmind.eventHub.emitAsync(EventType.COMPONENT_REMOVE, {
156-
componentId: component.__componentId,
157-
componentInstanceId,
158-
name,
159-
})
160-
}
161-
}, [])
133+
react.useLayoutEffect(() => {
134+
overmind.eventHub.emitAsync(EventType.COMPONENT_ADD, {
135+
componentId: component.__componentId,
136+
componentInstanceId,
137+
name,
138+
paths: Array.from(tree.pathDependencies) as any,
139+
})
162140

163-
react.useLayoutEffect(() => {
164-
tree.stopTracking()
165-
overmind.eventHub.emitAsync(EventType.COMPONENT_UPDATE, {
141+
return () => {
142+
;(overmind as any).proxyStateTree.disposeTree(tree)
143+
overmind.eventHub.emitAsync(EventType.COMPONENT_REMOVE, {
166144
componentId: component.__componentId,
167145
componentInstanceId,
168146
name,
169-
flushId,
170-
paths: Array.from(tree.pathDependencies) as any,
171147
})
148+
}
149+
}, [])
150+
151+
react.useLayoutEffect(() => {
152+
tree.stopTracking()
153+
overmind.eventHub.emitAsync(EventType.COMPONENT_UPDATE, {
154+
componentId: component.__componentId,
155+
componentInstanceId,
156+
name,
157+
flushId,
158+
paths: Array.from(tree.pathDependencies) as any,
172159
})
173-
tree.track(forceRerender)
174-
}
160+
})
161+
tree.track(forceRerender)
162+
}
175163

176-
const suspend = (cb) => {
177-
const value = cb()
164+
return tree.state
165+
}
178166

179-
if (value === null || value === undefined) {
180-
;(overmind as any).proxyStateTree.disposeTree(tree)
167+
const useActions = <Config extends IConfiguration>(): Overmind<Config>['actions'] => {
168+
const overmind = react.useContext(context) as Overmind<Config>
181169

182-
throw new Promise((resolve) => {
183-
const dispose = overmind.addFlushListener(() => {
184-
const newValue = cb()
170+
if (!(overmind as any).mode) {
171+
throwMissingContextError()
172+
}
173+
174+
return overmind.actions
175+
}
185176

186-
if (newValue === null || newValue === undefined) {
187-
return
188-
}
177+
const useEffects = <Config extends IConfiguration>(): Overmind<Config>['effects'] => {
178+
const overmind = react.useContext(context) as Overmind<Config>
189179

190-
dispose()
191-
resolve()
192-
})
193-
})
194-
}
180+
if (!(overmind as any).mode) {
181+
throwMissingContextError()
182+
}
183+
184+
return overmind.effects
185+
}
195186

196-
return value
197-
}
187+
const useReaction = <Config extends IConfiguration>(): Overmind<Config>['reaction'] => {
188+
const overmind = react.useContext(context) as Overmind<Config>
189+
190+
if (!(overmind as any).mode) {
191+
throwMissingContextError()
192+
}
193+
194+
return overmind.reaction
195+
}
196+
197+
export const createStateHook = <Config extends IConfiguration>(): Overmind<Config>['state'] => {
198+
return useState as any
199+
}
200+
201+
export const createActionsHook = <Config extends IConfiguration>(): Overmind<Config>['actions'] => {
202+
return useActions as any
203+
}
204+
205+
export const createEffectsHook = <Config extends IConfiguration>(): Overmind<Config>['effects'] => {
206+
return useEffects as any
207+
}
208+
209+
export const createReactionHook = <Config extends IConfiguration>(): Overmind<Config>['reaction'] => {
210+
return useReaction as any
211+
}
212+
213+
export const createHook = <Config extends IConfiguration>(): (() => {
214+
state: Overmind<Config>['state']
215+
actions: Overmind<Config>['actions']
216+
effects: Overmind<Config>['effects']
217+
addMutationListener: (cb: IMutationCallback) => () => void
218+
reaction: Overmind<Config>['reaction']
219+
}) => {
220+
return () => {
221+
const state = useState<Config>()
222+
const actions = useActions<Config>()
223+
const effects = useEffects<Config>()
224+
const overmind = react.useContext(context) as Overmind<Config>
198225

199226
return {
200-
state: tree.state,
201-
actions: overmind.actions,
202-
effects: overmind.effects,
203-
addMutationListener: overmind.addMutationListener,
227+
state,
228+
actions,
229+
effects,
204230
reaction: overmind.reaction,
205-
suspend,
231+
addMutationListener: overmind.addMutationListener
206232
}
207233
}
208234
}

0 commit comments

Comments
 (0)