diff --git a/src/UseStateLink.tsx b/src/UseStateLink.tsx index 0cf3001c..1580b00b 100644 --- a/src/UseStateLink.tsx +++ b/src/UseStateLink.tsx @@ -548,21 +548,45 @@ export function useState( export function useState( source: SetInitialStateAction | State ): State { - let sourceIsInitialValue = true - if (typeof source === 'object' && source !== null) { - const statemethodsSource = source[self] - if (statemethodsSource) { - // it is already state object - source = statemethodsSource; // get underlying StateMethods - sourceIsInitialValue = false + const parentMethods = typeof source === 'object' && source !== null ? + source[self] as StateMethodsImpl | undefined : + undefined; + if (parentMethods) { + if (parentMethods.isMounted) { + // Scoped state mount + // eslint-disable-next-line react-hooks/rules-of-hooks + const [, setValue] = React.useState({}); + return useSubscribedStateMethods( + parentMethods.state, + parentMethods.path, + () => setValue({}), + parentMethods)[self]; + } else { + // Global state mount or destroyed link + // eslint-disable-next-line react-hooks/rules-of-hooks + const [value, setValue] = React.useState({ state: parentMethods.state }); + return useSubscribedStateMethods( + value.state, + parentMethods.path, + () => setValue({ state: value.state }), + value.state)[self]; } + } else { + // Local state mount + // eslint-disable-next-line react-hooks/rules-of-hooks + const [value, setValue] = React.useState(() => ({ state: createStore(source) })); + const result = useSubscribedStateMethods( + value.state, + RootPath, + () => setValue({ state: value.state }), + value.state); + React.useEffect(() => () => value.state.destroy(), []); + const devtools = useState[DevToolsID] + if (devtools) { + result.attach(devtools) + } + return result[self]; } - const statemethods = useStateMethods(source as SetInitialStateAction); - const devtools = useState[DevToolsID] - if (sourceIsInitialValue && devtools) { - statemethods.attach(devtools) - } - return statemethods[self]; } /** @@ -670,54 +694,6 @@ export function DevTools(state: State): DevToolsExtensions { /// INTERNAL SYMBOLS (LIBRARY IMPLEMENTATION) /// -function useStateMethods( - source: StateMethods -): StateMethodsImpl; -function useStateMethods( - source: SetInitialStateAction -): StateMethodsImpl; -function useStateMethods( - source: SetInitialStateAction | StateMethods -): StateMethodsImpl { - const parentLink = source instanceof StateMethodsImpl ? - source as StateMethodsImpl : - undefined - if (parentLink) { - if (parentLink.isMounted) { - // Scoped state mount - // eslint-disable-next-line react-hooks/rules-of-hooks - const [, setValue] = React.useState({}); - const link = useSubscribedStateMethods( - parentLink.state, - parentLink.path, - () => setValue({}), - parentLink); - return link; - } else { - // Global state mount or destroyed link - // eslint-disable-next-line react-hooks/rules-of-hooks - const [value, setValue] = React.useState({ state: parentLink.state }); - const link = useSubscribedStateMethods( - value.state, - parentLink.path, - () => setValue({ state: value.state }), - value.state); - return link; - } - } else { - // Local state mount - // eslint-disable-next-line react-hooks/rules-of-hooks - const [value, setValue] = React.useState(() => ({ state: createStore(source) })); - const link = useSubscribedStateMethods( - value.state, - RootPath, - () => setValue({ state: value.state }), - value.state); - React.useEffect(() => () => value.state.destroy(), []); - return link; - } -} - const EmptyDevToolsExtensions: DevToolsExtensions = { label() { /* */ }, log() { /* */ }