-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Rule proposal: ssr-friendly #2057
Comments
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) |
@ljharb I updated the description |
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 I am not sure how to check if this is done inside of a guard such as if (typeof window !== 'undefined') {
// I can use browser globals in here
} @ljharb you have any thoughts on how I could check to see if the usage of the code is guarded? |
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. |
Sometimes there might be - such as when a component mounts into a portal. |
So on the server it might just return |
But I could buy that these are edge cases and a consumer could add a |
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. |
Sounds good to me |
Watching this closely as this would be super useful for Gatsby |
I hope to take more of a look at this soon! |
One problem: this rule can only detect dom globals if the it is used in the currently linted file. That is, if you import a apiSomethingService, this plugin cannot inspect the import source file to find out whether it is using dom globals. |
Sure, this only would ensure that your own components are authored correctly, much like any linting rule :-) |
@alexreardon I'm very interested in this rule – let me know if you could use an assist in any way! Caveat: we both have the same experience level in writing ESLint plugins 😄 |
I'd also be interested in such rule, as mentioned above it could only detect dom globals within the currently linted file. Despite that, in FC case we can always rename an external service to a custom hook notation, thus enforcing the access within the useEffect. Detect event handlers, promises, async may also be difficult |
@alexreardon (or anyone), did you find the time to implement this? 😁 |
Hey all, what do you think of this implementation? |
As a workaround I'm also going to consider just disallowing window and global altogether in lint, exempting a file that exports helpers like EDIT, here's my implementation.
and
Finally a use case from a function that scrolls to an element:
nice thing about this is that it doesn't require anyone to learn obscure/platform-specific stuff, like "in React it's safe to use |
Hey @osdiab How did your approach work out? I'm thinking of going into a similar direction for my team as well. Ideally engineers can safely write SSR compatible code without having to think about all the various edge cases and SSR vs CSR |
@pelhage it worked fine for us! No issues throughout my team so far. |
In order to be SSR compliant, you can only access browser globals such as
window
,document
and so on, inside ofcomponentDidMount
,componentDidUpdate
andcomponentWillUnmount
A rule could be created to avoid the use of unguarded browser globals in other lifecycle methods.
Example of a guard:
Use of browser globals are allowed when:
componentDidMount
,componentDidUpdate
andcomponentWillUnmount
useEffect
oruseLayoutEffect
The text was updated successfully, but these errors were encountered: