preact: Error with undefined __hooks property

Hi,

sorry for this confusing issue, but I haven’t found anything so far:

I have the issue that __hooks is suddenly undefined: 2019-12-10 at 17 19

Both of the forEach before succeed, but here __hooks is suddenly undefined (ie it must be through a side effect of one the invokeEffect calls):

Error in console: 2019-12-10 at 17 20

My hooks.module.js (extended by some console.log() calls): 2019-12-10 at 17 20

I highlighted the one that is right before the error.

The component that is triggering this error seems innocent enough (it is not yet finished 😉):

Show screenshot

2019-12-10 at 17 23

Happy to provide any additional info, if you could give me some pointers on where to look.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (6 by maintainers)

Most upvoted comments

Ok wow, so I finally got it reproducible. (I don’t want to admit that finding this just took me around 4.5 hours 😬)

Please, before investing time into “fixing this”: if my code / architecture is 💩 (ie that is a “won’t fix”), please tell me beforehand so that I can clean it up on my side and you don’t have to support super obscure use cases. 😬

Here is the reproducer: https://codesandbox.io/s/mystifying-frost-u6b7v

  1. pass a state hook setter into a nested prop
  2. immediately call this setter synchronously
  3. in the inner element render something (somewhere else using render()) in an effect.

I have absolutely no idea what is happening here, but what I can tell you is:

  • if move the render() code outside of the useEffect it works.
  • if I remove the state hook setter call it works

I guess step 2 is not supposed to be done like this, but I actually have no idea anymore now 😄

@apfelbox I put up a PR that is aimed at fixing this issue. Sorry I totally missed that repro

Hmm - in your sandbox, you’re calling render() on an existing render root from within a component. That’s sortof like telling Preact to change a bunch of things, then during those changes also telling Preact to undo everything and make different changes.

In terms of architecture, I’m guessing you’re looking to implement some sort of authorization or gating thing - would it be possible to just render null instead of doing another whole render(<div>global</div>,container) call? A component with insufficient data or permissions rendering null to show nothing would be more in keeping with the philosophy of top-down rendering.

FWIW the error in your most recent screenshot essentially comes from this: calling render() inside of useEffect() actually wipes away a bunch of important state. Wrapping that render() in a setTimeout() would fix the issue if you are 100% sure you want to use this approach.