Skip to content
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

Add eslint rule to error on reads or writes to refs in render #24506

Closed
wants to merge 2 commits into from

Conversation

devongovett
Copy link
Contributor

@devongovett devongovett commented May 5, 2022

Summary

After some discussion on the useEvent RFC and on Twitter, I and others learned that writing to refs during render is not allowed. This is documented in the new docs, but since this seems like it could be fairly common gotcha, I thought it might be useful to add to the eslint plugin.

I added a new rule (react-hooks/pure-render) that is meant to detect non-pure code in render functions. At the moment, it only detects reads or writes to refs, but it could be expanded later to detect other patterns as well potentially.

One pattern that the rule still allows is the lazy init pattern as documented here. This is detected by checking whether the access is inside an if statement that compares the value with the initial value passed to useRef.

(Side question: is this lazy init pattern really safe all the time, or only when you're sure the ref will never be reset back to its initial value?)

How did you test this change?

Added unit tests. I also ran the plugin on the React Aria code base and found a number of places that we will need to update. Verified that they all seemed valid.

const readError = {
message:
'Reading from refs during rendering is not allowed. See https://beta.reactjs.org/apis/useref',
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like some help with these error messages. I'm not sure exactly how much info we'd like to expose in the message vs in the docs link.

Also, would be nice if we could link directly to the "Pitfall" heading on that docs page, but right now it doesn't seem to have an anchor link.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job.

@sizebot
Copy link

sizebot commented May 5, 2022

Comparing: 547b707...18d2eea

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 131.58 kB 131.58 kB = 42.15 kB 42.15 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 136.82 kB 136.82 kB = 43.70 kB 43.70 kB
facebook-www/ReactDOM-prod.classic.js = 440.68 kB 440.68 kB = 80.35 kB 80.34 kB
facebook-www/ReactDOM-prod.modern.js = 425.89 kB 425.89 kB = 78.17 kB 78.17 kB
facebook-www/ReactDOMForked-prod.classic.js = 440.68 kB 440.68 kB = 80.35 kB 80.35 kB
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.min.js +8.52% 25.67 kB 27.85 kB +5.78% 8.79 kB 9.30 kB
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +5.23% 87.66 kB 92.24 kB +5.10% 20.81 kB 21.87 kB

Generated by 🚫 dangerJS against 18d2eea

@devongovett
Copy link
Contributor Author

hey, is there any interest in integrating this plugin or should I split it out into a separate package?

Copy link

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions bot added the Resolution: Stale Automatically closed due to inactivity label Apr 10, 2024
Copy link

Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you!

@github-actions github-actions bot closed this Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Resolution: Stale Automatically closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants