Description
- based on: Intent to Ship: useId reactwg/react-18#111
- sandbox: https://codesandbox.io/s/admiring-oskar-mqwdm?file=/src/App.js
Origins
Historically SSR was requiring some extra components to create a special "server" environment. Usually the ServerApplication is expected to be wrapped with different collectors
and providers
in order to power code splitting, style extraction, media queries, and many other things, some part of which don't have to be used on the client side, or even cannot exists at all.
ClientSide in turn, might contain some elements not required for the Server
The problem
According to my experiments for the proper use of useId
one does not need ideally matching component trees - any number of "wrappers" are allowed, and only having "more than one child" is breaking id generation, however it does not cause any hydration id and cannot be detected without a context-aware test.
const ServerProvider = ({ children }) => (
<context.Provider value={"server"}>
<SugarComponent>{children}</SugarComponent>
</context.Provider>
);
export const ServerApp = () => {
return (
<ServerProvider>
{/* this one is breaking */}
{/* <SugarComponent /> */} 👈 having this one will break id generation
<SugarComponent>
<App /> 👈 client will render only this
</SugarComponent>
</ServerProvider>
);
The question
What level of similarity is really required? What actually matters - the path(so internals of siblings do not matter), or everything "before this point"(probably not due to Selective Hydration)?
How one can understand are component trees are similar enough, or one should not try to do that, comparing the expected behavior (matching Ids) without relying on implementation details of useId
(currently one has to)