facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
228.46k stars 46.75k forks source link

Bug: eslint-plugin-react-hooks false positive conditional call after foreach #24791

Open Newbie012 opened 2 years ago

Newbie012 commented 2 years ago

React version:

    "react": "^18.2.0",
    "react-dom": "^18.2.0"

    "eslint": "^8.18.0",
    "eslint-plugin-react-hooks": "^4.6.0",

Steps To Reproduce

  1. Open https://stackblitz.com/edit/vitejs-vite-tpaumc?file=src%2FApp.tsx&terminal=dev
  2. Run npx eslint src
  3. Get the following error:
error  React Hook "React.useState" is called in function "App.View" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"  react-hooks/rules-of-hooks

Link to code example: https://stackblitz.com/edit/vitejs-vite-tpaumc?file=src%2FApp.tsx&terminal=dev

The current behavior

Given the following pattern:

const MyComponent = () => {
  return <MyComponent.Ready />;
}

MyComponent.Ready = () => {
  const [...] = useX();

  return (...);
}

I get the following error:

error React Hook "React.useState" is called in function "MyComponent.Ready" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks

The expected behavior

Since MyComponent.Ready is an actual component, I shouldn't get this error.

eps1lon commented 2 years ago

As a workaround you can do

const Ready = () => {}
MyComponent.Ready = Ready

This has the benefit of giving your component a name in devtools and component stacks.

export default () => {} is also recognized as a component so "anonymous component names" are not supported does not seem like a sufficient argument to close this as "working as expected".

cbclemmer commented 2 years ago

I created a pull request that should resolve this issue (#24839). I think it should check the name of the property of the component instead of the name of the variable assigned to the anonymous function.

Santosh130602 commented 3 months ago

The error you are seeing is because the function App.View is being treated as neither a proper React component nor a custom hook. React components must start with an uppercase letter, and the hooks rule of hooks enforces that hooks can only be called within function components or other hooks. To resolve this, you should rename App.View to start with an uppercase letter. Additionally, it's better to define the nested component separately and then use it within the main App component.

const MyComponent = () => { return ; }

MyComponentReady = () => { const [...] = useX();

return (...); }