hookstate icon indicating copy to clipboard operation
hookstate copied to clipboard

Hookstate error 111 doesn't exist

Open mattangus opened this issue 3 years ago • 9 comments
trafficstars

My application has thrown a hookstate error 111 with the link https://hookstate.js.org/docs/exceptions/#hookstate-111. This does not exist in the documentation.

mattangus avatar Aug 29 '22 14:08 mattangus

yes, it is v4 exception. It means you are switching a state source on rerender, ie. the initial value to useHookstate points to a different State on rerender. In code the exceptions is: InitStateStoreSwitchover The docs will get updated for this exception.

avkonst avatar Sep 04 '22 05:09 avkonst

Is there a way to turn this off or bypass it somehow? It's causing hot module replacement in vite.js to fail.

ayodeji-jackson avatar Sep 04 '22 22:09 ayodeji-jackson

hmm... "It's causing hot module replacement in vite.js to fail." this should not be the cause... but when it throws this exception, what property do you acccess? what type is it? what object type is it?

avkonst avatar Sep 04 '22 23:09 avkonst

I don't even need to access anything. When vite tries to perform hmr after detecting changes in my code, the app crashes and this error is shown in the console. But then if i make another code change, hmr works.

ayodeji-jackson avatar Sep 05 '22 00:09 ayodeji-jackson

could you please create a reproducer repo? what state value do you provide to hookstate?

avkonst avatar Sep 05 '22 01:09 avkonst

https://github.com/ayodeji-jackson/vendre

I have two global states using hookstate. both are arrays.

ayodeji-jackson avatar Sep 05 '22 01:09 ayodeji-jackson

thanks. I will have a look later in the evening. It looks like Vite reloads globals but does not reload React state behind useState, which is clearly a problem, which makes useState bug-prone under hot reload in Vite. You basically end up with one state behind a global variable and another one captured in component state on the previous rerender. This makes the globals leaking under hmr in vite. I do not think this is the issue with react-scripts, but I will double check. I am not sure what to do to fix it: removing the exception is possible but the problems will appear later in the app, leaving exception is a problem for vite...

avkonst avatar Sep 05 '22 01:09 avkonst

oh yeah. keeping previous state on component re-render is one of vite's features. do you think using hookstate for all local states will fix it? or i could check if disabling this feature is an option.

ayodeji-jackson avatar Sep 05 '22 02:09 ayodeji-jackson

local state is not impacted.. it is a global one i think... please let me know if it can be tuned...

avkonst avatar Sep 09 '22 07:09 avkonst

When setting your states, use arrow function to prevent this error, like;

const test = hookstate(null);

export function useTestState() { return useHookstate(()=>test); //Do not useHookstate(test); }

hope this helps.

HidayetCanOzcan avatar Nov 23 '22 02:11 HidayetCanOzcan

Having the same issues in Next.js v13.0.5. Getting Error: HOOKSTATE-111 [path: /] when hot module reloading.

useHookstate(()=>test) does not work for me sadly. The error is gone, but the code doesn't work as before.

Any other ways to get around this? 🙏🏻

oskarengstrom avatar Nov 27 '22 23:11 oskarengstrom

If error is gone after using arrow function, check your code again, because if that was the reason you are getting 111 error it means your state was updating one step behind. You maybe adapted this, structured your code and now your code doesnt work it used to be :) I am talking blindly of course, maybe some code snippets?

HidayetCanOzcan avatar Nov 28 '22 10:11 HidayetCanOzcan

Yeah, sorry, should have posted a snippet. Here goes:

// pages/index.js 

import { useHookstate, none, hookstate } from "@hookstate/core";

const globalState = hookstate([
  { task: "do one thing" },
  { task: "do enother thin gs" },
]);

export default function Home() {
  const todos = useHookstate(globalState);

  return (
    <div style={{ display: "grid", placeItems: "start" }}>
      {todos.map((todo, i) => (
        <Todo todo={todo} key={i} />
      ))}
      <button onClick={() => todos.merge([{ task: "new todo" }])}>
        Add new
      </button>
    </div>
  );
}

const Todo = ({ todo }) => {
  return (
    <div>
      <input
        value={todo.task.get()}
        onChange={(e) => todo.task.set(e.target.value)}
      />
      <button onClick={() => todo.set(none)}>Delete</button>
    </div>
  );
};

In this example above I get the 111 error on hmr, but the code works apart from that.

If I do const todos = useHookstate(() => globalState); the error disappears, but todo.task.get() suddenly isn't getting the value but returns a Proxy instead.

oskarengstrom avatar Nov 28 '22 10:11 oskarengstrom

Try to seperate your states and import them and you wont get this error and your hooks will work as you wanted. I think the cause of the problem is strict mode.

Or a better solution will be using useHookstateMemo

function useGlobalState(){ const globalState = useHookstateMemo(()=>[ { task: "do one thing" }, { task: "do enother thin gs" }, { task: "do enother thin gs" }, ],[]); return useHookstate(globalState) }

and you can use it in your component like;

const todos = useGlobalState();

HidayetCanOzcan avatar Dec 01 '22 06:12 HidayetCanOzcan

@avkonst you should close some of the issues, I really like hookstate but its getting harder to convince people to use this awesome tool. :)

HidayetCanOzcan avatar Dec 02 '22 20:12 HidayetCanOzcan

this is now part of the docs: https://hookstate.js.org/docs/exceptions/#hookstate-111 closing.

mattangus avatar Dec 02 '22 23:12 mattangus

@HidayetCanOzcan sure... I am just overloaded with stuff. 60+ hours per week at work. And it is Summer time where I live. But I will clean it up soon.

avkonst avatar Dec 03 '22 10:12 avkonst

The error 111 is not part of the docs yet, but I will update soon

avkonst avatar Dec 03 '22 10:12 avkonst

Oops saw 101 and read 111 😅

mattangus avatar Dec 03 '22 10:12 mattangus

Just wanna confirm that this worked for me! Thanks a lot!

function useGlobalState(){ const globalState = useHookstateMemo(()=>[ { task: "do one thing" }, { task: "do enother thin gs" }, { task: "do enother thin gs" }, ],[]); return useHookstate(globalState) }

and you can use it in your component like;

const todos = useGlobalState();

oskarengstroem avatar Dec 03 '22 12:12 oskarengstroem

Just wanna confirm that this worked for me! Thanks a lot!

function useGlobalState(){ const globalState = useHookstateMemo(()=>[ { task: "do one thing" }, { task: "do enother thin gs" }, { task: "do enother thin gs" }, ],[]); return useHookstate(globalState) } and you can use it in your component like; const todos = useGlobalState();

No problem, glad to help :)

HidayetCanOzcan avatar Dec 03 '22 18:12 HidayetCanOzcan

see related follow up https://github.com/avkonst/hookstate/issues/364

avkonst avatar Dec 18 '22 23:12 avkonst

docs updated

avkonst avatar Dec 18 '22 23:12 avkonst