-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent HOOKSTATE-111 exception being raised during Vite and NextJS HMR #364
Comments
hi, this gets really annoying when combining global states with local ones, i can't figure out any workarounds at the moment, you got any @avkonst ? also, please explain when exactly does the issue occur, is it when i use a global state i'm using vite UPDATE: // global map of key and state
import { hookstate } from '@hookstate/core';
const global_store: Map<any, State<any, any>> = new Map();
export function get_store(key: any) {
let store = global_store.get(key);
if (!store) {
store = hookstate(values);
global_store.set(key, store);
}
return store;
}
export function delete_store(key: any) {
global_store.delete(key)
}
// in component
import { useHookstate } from '@hookstate/core';
import { get_store, delete_Store } from "./global_store"
import { useEffect } from 'react';
export function Login() {
const store = useHookstate(get_store("my_store"))
useEffect(() => {
return () => delete_store("my_store")
}, [])
return (
<>
<input onChange={(e: any) => store.set(e.target.value)} />
<p>{JSON.stringify(store.get())}</p>
</>
)
} now i have to find a way to prevent duplicate keys and uuid is not an option, hope this gets fixed soon <3 |
yep, had this issue with next.js and vite HMR |
Same with Expo/React-Native HMR |
This is generally an issue whenever the state you want to use depends on another state. E.g., const keyState = hookstate('key')
const stateMap = new Map<string, State>()
const MyComponent = () => {
const currentKey = useHookstate(keyState)
const state = useHookstate(stateMap.get(currentKey))) // HOOKSTATE-111 exception thrown when keyState changes
return null
} My current workaround is to use a keyed child component: const keyState = hookstate('key')
const stateMap = new Map<string, State>()
const MyComponent = () => {
const currentKey = useHookstate(keyState)
return <MyChildComponent currentKey={currentKey} key={currentKey}/> // note: key is necessary
}
const MyChildComponent = ({currentKey}) => {
const state = useHookstate(stateMap.get(currentKey))) // no more HOOKSTATE-111 exception
} A fix for this would be greatly appreciated. |
The fix for the issue described intially is quite hard. I have not explored how to accomplish it. Interestlngly it did not happen with react-scripts... new with Vite |
Any news on this? const productEditorBottomSheetGlobalState = hookstate<{
isOpen?: boolean
data?: Partial<ProductsDto> | undefined
}>(
{ isOpen: false, data: undefined },
extend(extensions('productEditorBottomSheet'))
)
export function useProductFormBottomSheet() {
const state = useHookstate(
productEditorBottomSheetGlobalState,
extensions('productEditorBottomSheetHook')
)
const showBottomSheet = useEvent(() => {
state.merge({ data: none, isOpen: true })
})
const close = useEvent(() => {
state.merge({ isOpen: false })
})
const isOpen = state.isOpen?.value
const editProduct = useEvent((data: Partial<Partial<ProductsDto>>) => {
state.merge({ isOpen: true, data })
})
return useMemo(() => {
return {
data: state.data,
showBottomSheet,
close,
isOpen,
editProduct,
}
}, [close, editProduct, isOpen, showBottomSheet, state.data])
} and then I use When I edit some code and the page refreshes, I always get this error How can I fix this? |
Here is an easy fix to this issue: import { hookstate, useHookstate } from "@hookstate/core";
import { useEffect } from "react";
const defaultState = {
count: 0,
};
const globalState = hookstate(defaultState);
export const useStore = () => {
const state = useHookstate(defaultState);
const stateVal = globalState.get({ noproxy: true });
useEffect(() => {
state.set(stateVal);
}, [stateVal]);
return state;
}; |
@solidsnail can you explain your solution please? By a quick reading of the code, it sounds like causing a lot of re-renders.. |
The crash occurs when you pass a hookstate to another hookstate as defaultValue, to avoid this you can create a "copycat" state and grab the real state value using noproxy: true which stops the code from listening to changes, and instead we use the good old useEffect to listen to its changes and update the "copycat" state. const state = useHookstate(
productEditorBottomSheetGlobalState, // <=== This is a real proxy state which should not be passed as defaultValue
extensions('productEditorBottomSheetHook')
) @apperside Here you are hooking two states together which causes the crash when the HMR tries to reconciliate the changes |
@avkonst I keep running into scenarios where it would be incredibly helpful if it were possible to dynamically change which state is being observed in |
@speigg Ok. This was long time ago when I looked at it, but here is what I remember:
Potential fix could possibly be around resetting local state when a new (non matching) global state is detected, but there are probably consequences and complications. As far as I remember, local component state (not the one used by hookstate, but other, like effects, memo, etc.) was also preserved on hot reload and it captured all of the callbacks to manage the global state (old state from the initial render). As a result, even if we make hookstate to workaround the mentioned exception, all callbacks / actions in reactions will still refer to the old global state. This is where I stopped my investigation last year, understanding that the fix would not be easy, if even possible. And I knew that it was vite specific as react-scripts did hot reload and did not cause this problem. The things might changed since last time I looked at it. So all of the above needs reinvestigation and confirmation. I am happy if you look at it, confirm the problem and develop state rebind solution. The local isolated test to make working is described above. PS: I am still maintaining and looking after the project, but significant development is a problem for me as I moved to very rapid start up 2+ years ago at very senior architect role and I barely have time now for family and sport. I appreciate if you can crack this problem. I can help with guidance. You know my email. |
FWIW, I'm getting this with React hot reloading. I can't say if it's an artifact of my setup or not since I barely understand the issue in the first place. But I thought I would report it anyway. |
Upvote this if you are interested in this feature.
The text was updated successfully, but these errors were encountered: