-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
feat(v2): add a way to exclude components from build-time prerendering #2323
Conversation
Deploy preview for docusaurus-2 ready! Built with commit 63ee326 |
import React, {useEffect, useState} from 'react'; | ||
|
||
const ClientOnly = ({children}) => { | ||
const [isClient, setIsClient] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think isComponentMounted
will be a better name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
import React, {useEffect, useState} from 'react'; | ||
|
||
const BrowserOnly = ({children}) => { | ||
const [isClient, setIsClient] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw I'm wondering if we can use the ExecutionEnvironment.canUseDOM
instead, then there's no need for a state right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why so? This state is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the diff between doing your way and this:
function BrowserOnly({children}) => {
return ExecutionEnvironment.canUseDOM && children;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seemed to me that all the work of this component is to use useEffect
, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and I think we don't even need useEffect
here. Can you try what I've proposed and see whether there's any difference? :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that none of the options actually works, it really puzzled me and in complete dismay 🤒
P.S. For the test, I used the @u-wave/react-vimeo
component in the MDX file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So even your current implementation doesn't work? Luckily we test out first lol. Maybe the component is running some side effects that relies on browser environments being present during import
. In that case there's no way around it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not exactly, rather why something does not work, this component on some dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some investigation I found out that build fails if a component using a window
object is imported, how is this possible? Therefore the BrowserOnly
component is useless here 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went to test this component out and it doesn't seem to work. I'm not sure why but I think we can't let the children be JSX, we have to let it be a render function.
To reproduce the bug, add
<BrowserOnly>{window.location.pathname}</BrowserOnly>
to any page and try to build it. It will fail.
But if you do this:
<BrowserOnly>{() => window.location.pathname}</BrowserOnly>
along with the suggested change of doing children()
within BrowserOnly.js
, it will be fine.
Will need to change the docs also and say the contents have to be a render function. Will also be good to have tests.
|
||
import React, {useEffect, useState} from 'react'; | ||
|
||
const BrowserOnly = ({children}) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also works and is shorter IMO.
function BrowserOnly({children}) {
return ExecutionEnvironment.canUseDOM && children != null && <>{children()}</>;
};
Let's use function declaration for functional components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, although this does not solve the issue of importing components using window
.
For example, if I just import this component in the MDX file, then I will have an error during the building that the window
is not defined.
import {Replay} from 'vimond-replay';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, users will have to lazy load the component after the component has mounted. There's no way we can handle that with the suggested component here.
@lex111 shall we try to get this into the next release? |
@yangshun done ✔️ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will fix this if you don't get to it by tonight so that we can include this in the next release.
website/docs/docusaurus-core.md
Outdated
import BrowserOnly from '@docusaurus/BrowserOnly'; | ||
|
||
<BrowserOnly> | ||
{/* Something that should be excluded during build process prerendering. */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to give an example to show that children
should be a render function and not normal children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, done ✔️
Motivation
Resolve #2273.
Have you read the Contributing Guidelines on pull requests?
Yes
Test Plan
ClientOnly
put component that usedwindow
object, eg.Related PRs
(If this PR adds or changes functionality, please take some time to update the docs at https://github.com/facebook/docusaurus, and link to your PR here.)