Atom State breaks when the same component is used across multiple windows
ChrisBoon opened this issue · 2 comments
Zedux Version
1.2.1. Also tested 1.2.0.
Description
When you use setInternals to work across windows there appears to be a limitation that the same component cannot be used in multiple windows. Eg if I have a WindowFrame
wrapper component that accesses a theme atom via useAtomState or useAtomValue to update its theme and I open 3 different windows that contain this WindowFrame component, only one of them will receive live updates. If, instead, each window uses a unique react component and gets the theme from the atom separately, it works fine.
This appears to be due to how useAtomInstance generates a key using const dependentKey = useReactComponentId()
. This appears to make the keys non-unique across windows. One way to see this is likely the case is to see that the graph only seems to have the number of dependents that matches the maximum instance count in a given window.
This is causing us quite an issue as our app lets users pop out different parts of dashboards and we chose Zedux specifically because it has great multi-window support (it's great generally, but this was the deciding factor), but as we've begun standardizing and abstracting to generic components this issue has caused parts of our WIP app to stop live updating.
Below I've included a small reproduction using window.open. In our real app we use OpenFin, but the issue is the same either way. I guess ideally we'd be able to inject the window name or uuid into the dependentKey.
Reproduction
Please see this demo in StackBlitz (I had trouble getting windows to work well in codesandbox). Note that I disabled strict mode and that re-enabling it causes a slightly different behavior. I've tried to add notes in the comments and on the UI itself to explain how to trigger the issue, but am more than happy to try and make clearer.
https://stackblitz.com/edit/vitejs-vite-q37ggg?file=package.json
Thanks for any help or advice you can give on this.
Hey @ChrisBoon! Thank you so much for taking the time to put together such a good reproduction! I was able to see the issue immediately. Your assessment is correct, useReactComponentId
is not generating a unique id across windows.
useReactComponentId
relies on React's useId
for this. And React fortunately provides a way to control these per-app using the identifierPrefix
option on react-dom's createRoot
. For example:
ReactDOM.createRoot(document.getElementById('root'), {
identifierPrefix: document.title, // or location.pathname or any uuid
}).render(
<App />
);
Updated stackblitz example:
https://stackblitz.com/edit/vitejs-vite-swvdpt?file=src%2Fmain.jsx
That's awesome. My bad for not following it to its conclusion and reading the react docs on useId - haven't come across that one before.
Thanks for another really quick response, really appreciate it.