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

[eslint] Check forwardRef callbacks #17255

Merged
merged 5 commits into from
Nov 17, 2019
Merged

[eslint] Check forwardRef callbacks #17255

merged 5 commits into from
Nov 17, 2019

Conversation

dprgarner
Copy link
Contributor

@dprgarner dprgarner commented Nov 2, 2019

Closes #17220

This checks that the rules of hooks apply to callback arguments of forwardRef.

I'm unsure whether this counts as a backwards-incompatible change or not. It's making the linter stricter, but I'd only expect new errors to be reported in code that's already breaking the rules of hooks. There is a potential edge-case of code with a forwardRef-wrapped component using a non-hook function with a name starting with "use"; this change would now return a false positive.

@dprgarner dprgarner changed the title [eslint] Check forwardRef callbacks (#17220) [eslint] Check forwardRef callbacks Nov 2, 2019
@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 2, 2019

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 54a180a:

Sandbox Source
quirky-cohen-u62go Configuration

@sizebot
Copy link

sizebot commented Nov 2, 2019

Details of bundled changes.

Comparing: f4148b2...54a180a

eslint-plugin-react-hooks

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
eslint-plugin-react-hooks.development.js +1.2% +1.1% 75.25 KB 76.19 KB 17.31 KB 17.5 KB NODE_DEV
eslint-plugin-react-hooks.production.min.js 🔺+1.4% 🔺+1.0% 20.14 KB 20.44 KB 6.9 KB 6.97 KB NODE_PROD

Size changes (stable)

Generated by 🚫 dangerJS against 54a180a

@sizebot
Copy link

sizebot commented Nov 2, 2019

Details of bundled changes.

Comparing: f4148b2...54a180a

eslint-plugin-react-hooks

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
eslint-plugin-react-hooks.development.js +1.2% +1.1% 75.26 KB 76.2 KB 17.32 KB 17.5 KB NODE_DEV
eslint-plugin-react-hooks.production.min.js 🔺+1.4% 🔺+1.0% 20.16 KB 20.45 KB 6.91 KB 6.97 KB NODE_PROD

Size changes (experimental)

Generated by 🚫 dangerJS against 54a180a

Copy link
Collaborator

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

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

The reason these tests fail without changing the implementation is that you didn't name the function not because it's passed to forwardRef. React.forWardRef(function Foo() {}) will be linted for rules of hooks.

It also encourages you to name the function or variable passed to forwardRef so that react can compute a proper display name (besides "unknown").

But this should probably be covered by a different rule.

The only issue I would have with the tests is that you didn't specify props nor ref argument which doesn't make much sense at the moment.

And it might make sense to apply this to React.memo as well.

@dprgarner
Copy link
Contributor Author

Thanks for the feedback. I'll add explicit props and ref arguments to the test cases, and generalise this to check React.memo too.

The react/display-name rule checks that components have a display name. In the codebase where I spotted this issue, we set displayName as a property on the component returned by forwardRef, which then causes this rule to pass. I don't know if it makes sense for this linting rule to be changed to require the forwardRef argument to be a named CapitalCase function, as setting the displayName property directly fixes the issue that the linting rule is checking for.

Should there be a linting rule enforcing CapitalCase function names in the arguments of forwardRef, though? Is the argument actually a component? The function signature isn't the same as for a functional component, and the forwardRef docs refer to the argument as a "render function" and don't use CapitalCase when naming it. Does this mean that the function argument to forwardRef shouldn't be using hooks at all?

});
`,
errors: [conditionalError('useCustomHook')],
},
Copy link
Collaborator

@gaearon gaearon Nov 8, 2019

Choose a reason for hiding this comment

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

Can we also add tests verifying how we handle React.whatever(props => ...) or whatever(props => ...)? i.e. the case where isReactFunction returns false.

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've added some more tests. The existing behaviour is to skip checking unnamed callbacks - there's a regression test in place for this.

@dprgarner dprgarner requested a review from gaearon November 16, 2019 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[eslint-plugin-react-hooks] Apply the rules of hooks to a forwardRef-wrapped component
5 participants