Skip to content

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

Closed
devongovett wants to merge 2 commits into
facebook:mainfrom
devongovett:eslint-refs
Closed

Add eslint rule to error on reads or writes to refs in render#24506
devongovett wants to merge 2 commits into
facebook:mainfrom
devongovett:eslint-refs

Conversation

@devongovett
Copy link
Copy Markdown
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
Copy Markdown
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.

Copy link
Copy Markdown

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
Copy Markdown

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
Copy Markdown
Contributor Author

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

@github-actions
Copy link
Copy Markdown

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
@github-actions
Copy link
Copy Markdown

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