react-spaces
react-spaces copied to clipboard
SSR on 0.2.0: ReferenceError: document is not defined
Describe the bug
react-spaces tries to access the document
global on the server side execution. Stack trace:
ReferenceError: document is not defined
at updateStyleDefinition (<snip>/node_modules/react-spaces/dist/index.js:1:6669)
at Object.addSpace (<snip>/node_modules/react-spaces/dist/index.js:1:12033)
at useSpace (<snip>/node_modules/react-spaces/dist/index.js:1:17621)
at SpaceInner (<snip>/node_modules/react-spaces/dist/index.js:1:20542)
at processChild (<snip>/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
at resolve (<snip>/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (<snip>/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (<snip>/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
at renderToString (<snip>/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
at renderPage (<snip>/node_modules/next/dist/next-server/server/render.js:53:851)
at Object.ctx.renderPage (webpack-internal:///./src/pages/_document.tsx:79:26)
at Function.getInitialProps (webpack-internal:///../../node_modules/next/dist/pages/_document.js:135:19)
at Function.MyDocument.getInitialProps (webpack-internal:///./src/pages/_document.tsx:87:83)
at loadGetInitialProps (<snip>/node_modules/next/dist/next-server/lib/utils.js:5:101)
at renderToHTML (<snip>/node_modules/next/dist/next-server/server/render.js:53:1142)
at async <snip>/node_modules/next/dist/next-server/server/next-server.js:98:97
To Reproduce Steps to reproduce the behavior:
- Use react-spaces in a server environment, e.g. nextjs
Expected behavior Should render as normal
Package versions (please complete the following information):
- React version: 17.0.1
- React spaces version: ^0.2.0
Desktop (please complete the following information):
- OS: Manjaro
- Browser Chrome
- Version 87
I see previously there was a separate dist folder for an SRR-enabled version of react-spaces, however I can't find any traces of it in the newest version. :) If you want I can set up a quick nextjs repro repo.
Hi @karl-run Thanks for reporting. If you could setup a repro repo that would be great!
Sure thing!
https://github.com/karl-run/react-spaces-repro
@karl-run I ran into this too, I think it's a problem w/ Next.js's SSR, the fix here worked for me.
@cktang88 It's correct that you can "fix" this issue by limiting the execution of react-spaces to the client. But a library such as react-spaces in typically something that you would want to execute on the server side because it's part of the layout.
The earlier you "exit" the rendering on your server, the more of the initial rendering has to be done on the client. In my app react-spaces was pretty high up in the rendering tree, so if I were to use the fix you linked I would just have a single page application, but with more steps. :)
Hi all. I've played around with the repro and whilst it's easy to stop the reference to document server side, because currently the library relies quite heavily on the first render to create the correct layout between spaces the result is not good once the styling/initial mark-up actually hits the client.
I'm looking into a solution to ensure the correct info makes it's way from server-side -> client-side to render the layout correctly and will keep you posted.
For now unfortunately the only workaround is to configure the react-spaces as client execution only.
I am still looking into this to see what's feasible.
I've released a small fix (v0.3.9
) to avoid document is not defined errors when components are being rendered in a server-side environment. However bear in mind that this is not a full SSR implementation.
Pro:
- Spaces and their content should now be able to be rendered server-side without error
Con:
- Space styling and positioning is not rendered server-side. Styling will still be rendered client-side once the component is hydrated however there is a caveat that all spaces must be explicitly given a unique
id
prop for this to currently work correctly rather than relying on a dynamically given id as default.
Ok. I've added full support (experimental) in v0.4.0
. It's opt in at the moment by added the <SSR />
component from the library before any use of spaces.
There are some caveats:
- You must be using React 18 as the functionality depends on new functionality in that version, namely the
useId()
hook for consistent ID generation between server and client renders. This does mean that you now do not explicitly need to set an id on spaces as mentioned before. - Ordering of spaces in the JSX/TSX matters in a SSR scenario. Because a
<Fill />
is dependent on renders of all anchored spaces around it to determine it's size, you should always place the<Fill />
space last within a parent. This is so that it's correct size is determined in the first render. I would imagine that if you are using stacked anchored spaces, then they should appear in the JSX/TSX in the order they are stacked also.
I know this has been a long time coming but would be good to know if this works for you in your use cases.
Going to close this as resolved. Feel free to reopen if you are still having issues.