-
-
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
[New] jsx-no-constructed-context-values
: add rule for unstable context values
#2763
[New] jsx-no-constructed-context-values
: add rule for unstable context values
#2763
Conversation
…when the value passed to a Context Provider will cause needless rerenders Adds a new rule that checks if the value prop passed to a Context Provider will cause needless rerenders. A common example is inline object declaration such as: ```js <Context.Provider value={{foo: 'bar'}}> ... </Context.Provider> ``` which will cause the Context to rerender every time this is run because the object is defined with a new reference. This can lead to performance hits since not only will this rerender all the children of a context, it will also update all consumers of the value. The search React does to search the tree can also be very expensive. Some other instances that this rule covers are: array declarations, function declarations (i.e. arrow functions), or new class object instantians.
Looks like tests are failing on ESLint version 4 |
Interesting! If destructing is not supported, I wonder if there's a lint rule we could add to this repo's eslint config that would disallow it. That would certainly make it easier for the next person. |
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.
Is this rule only useful with React 16.3+'s Context? What about regular context?
@ljharb This rule was built with React 16.3's contexts in mind and that's where the test coverage mainly lies. But its functionality is general in that it will detect any value that could change identity. Could you elaborate more on "regular contexts"? |
I mean like, pre-16.3 React context, like the |
This rule won't work for pre <16.3 contexts because that mechanism is fundamentally different to the context used for 16.3+ I don't know too much about the legacy context API, but reading the old docs, I believe it only lets you pass objects down the chain, returned from the method. |
Fair enough. |
Hi @ljharb just wanted to double check if there was still things that needed changing. |
Following up here to see if there's anything else needed before this can be merged. |
JSX-no-constructed-context-values
rule for unstable context valuesjsx-no-constructed-context-values
: add rule for unstable context values
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.
Rebased this; I think it looks good but I want to give it another look.
24dae08
to
ac98c0f
Compare
It's not released yet, right? I can see it in README, but eslint says that Definition for rule 'react/jsx-no-constructed-context-values' was not found |
Yes - check the readme on the latest tag, not on master, to see what’s released. |
Rule
JSX-no-constructed-context-values
Summary
Adds a new rule that checks if the value prop passed to a Context Provider will cause needless rerenders. A common example is inline object declaration such as:
which will cause the Context to rerender every time this code is run because the object is defined with a new reference. This is true for many other types of JS objects and variables.
Rationale
This can lead to performance hits since not only will this rerender all the children of a context, it will also update all consumers of the value. The search React does to search the tree can also be very expensive. Some other instances that this rule covers are: array declarations, function declarations (i.e. arrow functions), or new class object instantiates.
Possible Fixes
For inline values this can be fixed by wrapping the in-line declaration with
useMemo
oruseCallback
as the lint rule suggests. I think this can depend on the usage and specific implementation and thus an auto-fix rule is not provided. For the example above this would look like:Improvements
useCallback
for functions declarations/definitions, anduseMemo
for everything else. I was considering suggesting moving the reference outside of the component, but like I mentioned before I feel this can be case-by-case and I'm hesitant making this an auto-fix rule.Contributions
Thanks to @captbaritone for noticing the issue and creating the React hooks version which this is largely based off of, and huge thanks to @bradzacher for suggesting I make this rule open source here 👍