atlassian / react-sweet-state

Shared state management solution for React
https://atlassian.github.io/react-sweet-state/
MIT License
871 stars 55 forks source link

Container cleanup occurs after remounting, clearing state set by onInit #193

Closed s-taylor closed 1 year ago

s-taylor commented 1 year ago

Scenario:

I have a component that is linked with a container and has a scope.

Events:

This situation happens within react storybooks. I tried to reproduce it in pure react using two different components linked to the same container to ensure react performs an unmount and remount when switching, but did not experience the same problem. Perhaps I'm missing something here though.

I did notice that the cleanup happens on the next tick, so in theory it should be possible to replicate it in other environments. https://github.com/atlassian/react-sweet-state/blob/master/src/components/container.js#L79

Expected:

I would expect the cleanup to occur before mounting componentB. This option is preferred as it ensures you get clean state if you unmount the last component using a store, then remount another component using the same store.

Alternatively not perform the cleanup step at all if it would trigger after the same container is remounted. This would at least ensure the state is not destroyed, but state would be persisted across components even though the store was unmounted from the application entirely.

Example:

In my specific case, this causes a problem with using a singular component in storybooks.

https://codesandbox.io/p/sandbox/hungry-sea-ub8boh?file=%2Fsrc%2Ftest-components.story.tsx&selection=%5B%7B%22endColumn%22%3A25%2C%22endLineNumber%22%3A4%2C%22startColumn%22%3A25%2C%22startLineNumber%22%3A4%7D%5D

To see the issue, switch between the stories and view the logs.

albertogasparin commented 1 year ago

Thank you for providing a reproducible example. Seems like the issue is due to useSyncExternalStore using useEffect for subscriptions, however those are scheduled via requestAnimationFrame + postMessage and so there is a chance that a store cleanup happens between new component being rendered and subscription happening 😵‍💫