-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Open
Description
In order to be SSR compliant, you can only access browser globals such as window
, document
and so on, inside of componentDidMount
, componentDidUpdate
and componentWillUnmount
A rule could be created to avoid the use of unguarded browser globals in other lifecycle methods.
Example of a guard:
if (typeof window !== 'undefined') {
// I can use browser globals in here
}
Use of browser globals are allowed when:
- used in a guard
- used in
componentDidMount
,componentDidUpdate
andcomponentWillUnmount
- used in
useEffect
oruseLayoutEffect
- used in an event handler
Haroenv, thiagodebastos, ZebraFlesh, sidharthachatterjee, cbovis and 18 more
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
ljharb commentedon Nov 26, 2018
This sounds like an excellent rule, and I'm very much in favor of it. A PR is appreciated!
(Note, however, that it's also acceptable to access these things in event handlers - any component method or function that is only referenced by passing it in as a prop to an element, and never directly invoked)
alexreardon commentedon Nov 26, 2018
@ljharb I updated the description
alexreardon commentedon Dec 2, 2018
I have not had experience writing eslint plugins before. I see the first step as fairly straight forward: checking if browser globals are called inside of
componentDidMount
,componentDidUpdate
orcomponentWillUnmount
.I am not sure how to check if this is done inside of a guard such as
@ljharb you have any thoughts on how I could check to see if the usage of the code is guarded?
ljharb commentedon Dec 3, 2018
Even if guarded, if initial render behavior differs between client and server, that’s a bug - so there shouldn’t be any use outside of those methods, even guarded.
alexreardon commentedon Dec 3, 2018
Sometimes there might be - such as when a component mounts into a portal.
alexreardon commentedon Dec 3, 2018
So on the server it might just return
null
, whereas in the browser it might returnReactDOM.createPortal(children, el)
. I have seen this pattern aroundalexreardon commentedon Dec 3, 2018
But I could buy that these are edge cases and a consumer could add a
//eslint-ignore-next-line react/ssr-friendly
ljharb commentedon Dec 3, 2018
That would cause a render mismatch, i believe - if you want to conditionally render into a portal, you’d need to do that using state set in componentDidMount.
alexreardon commentedon Dec 3, 2018
Sounds good to me
sidharthachatterjee commentedon Apr 10, 2019
Watching this closely as this would be super useful for Gatsby
window
gatsbyjs/gatsby#12769alexreardon commentedon Apr 12, 2019
I hope to take more of a look at this soon!
13 remaining items