Skip to content
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

Kea does not unmount logic when using lazy components with suspense #150

Open
rschyboll opened this issue Aug 9, 2022 · 3 comments
Open

Comments

@rschyboll
Copy link

Hi!

After a long night of debugging, I have found a weird bug in kea, when using it with React.Suspense and lazy.
In short, when mounting a logic, in a component that is wrapped with a Suspense component, and in that component, is rendered a lazy component, the logic is mounted twice, but unmounted only once.

I don't have much knowledge of how Suspense works, but it seems, that it holds the livecycle of a component, until the lazy component gets loaded, and then it launches the component once again. But as kea mounts the logic outside of the component lifecycle, the mount method gets called twice (it seems, that the unmount useRef in the useMountedLogic is not preserved).

I've created a simple codesandbox, that showcases this issue:
https://codesandbox.io/s/kea-mount-suspense-bug-tuquvs?file=/src/app.js&fbclid=IwAR2KIVJDj2-jKQJa6Bmbtb-lSrpD-d8Xa3gAe_0FC1ErWBZmmiYXvCrDCAw

In the console, i'm logging the mount counter from kea's context. The logic is mounted in LogicComponent, which get's rendered when we choose a page. Tha pages are loaded with lazy and rendered in the LogicComponent. Then, when we return to page None, the component is unmounted, but the logic is still mounted.

To be honest, I have no ideas how to fix this, but if I could help you somehow with this issue, i'd be happy to.
And if that's some kind of issue on my side, then I would really appreciate any help with this :)

@rschyboll
Copy link
Author

Another thing i remembered today, is that the same thing is happening with React.StrictMode. When using it, all kea logics are mounted twice, but unmounted only once. According to the documentation, it mounts every component twice, to help with detecting side-effects.

@mariusandra
Copy link
Member

Hey, we officially don't support React Strict Mode. We must mount components while the component renders (not after or before), and as strict mode provides no additional controls over "everything happens twice", I had no choice but to not support it.

I had no idea suspense works in a similar way. I tried the codesandbox example and indeed this seems to be the case. Sadly I don't have any workaround here other than not using suspense. There might be a way to hook into React's internals to figure out what's happening, but this feels brittle. I'm happy to hear suggestions from someone more knowledgeable.

However in case this helps, in my own apps, I've avoided using code like that, and use my own global scene routing logic with kea-router. It lazy loading components, and can even be extended to preload logics and do even more complex operations. See here for a more complex sceneLogic example.

I know this isn't the answer you were looking for (1.5 years ago 😅), but it's the best I have today.

@wojteke
Copy link

wojteke commented Jun 10, 2024

Hi!

After a long night of debugging, I have found a weird bug in kea, when using it with React.Suspense and lazy. In short, when mounting a logic, in a component that is wrapped with a Suspense component, and in that component, is rendered a lazy component, the logic is mounted twice, but unmounted only once.

I don't have much knowledge of how Suspense works, but it seems, that it holds the livecycle of a component, until the lazy component gets loaded, and then it launches the component once again. But as kea mounts the logic outside of the component lifecycle, the mount method gets called twice (it seems, that the unmount useRef in the useMountedLogic is not preserved).

I've created a simple codesandbox, that showcases this issue: https://codesandbox.io/s/kea-mount-suspense-bug-tuquvs?file=/src/app.js&fbclid=IwAR2KIVJDj2-jKQJa6Bmbtb-lSrpD-d8Xa3gAe_0FC1ErWBZmmiYXvCrDCAw

In the console, i'm logging the mount counter from kea's context. The logic is mounted in LogicComponent, which get's rendered when we choose a page. Tha pages are loaded with lazy and rendered in the LogicComponent. Then, when we return to page None, the component is unmounted, but the logic is still mounted.

To be honest, I have no ideas how to fix this, but if I could help you somehow with this issue, i'd be happy to. And if that's some kind of issue on my side, then I would really appreciate any help with this :)

bug
skill issue

EDIT:

For context Just for context this is not a serious reply. @rschyboll just lost a bet with me so I had a privilage to reply to any issue he created in the above way.

I wanted to clarify it so please don't take this seriously 😄

Great work with the kea btw ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants