Skip to content

[DevTools Bug]: react-hooks/set-state-in-effect misses setState in useEffect for anonymous component callbacks passed to HOFs #35910

@maltesa

Description

@maltesa

Website or app

https://codesandbox.io/p/sandbox/github/codesandbox/sandbox-templates/tree/main/nextjs

Repro steps

Current behavior

react-hooks/set-state-in-effect reports setState in a normal component's useEffect, but misses the same pattern when the component is an anonymous callback passed to a higher-order function.

// app/ComponentToCheck.ts

import { useEffect, useState } from 'react'

const wrap = (value) => value

export function DirectComponent() {
  const [value, setValue] = useState(0)

  useEffect(() => {
    // Direct
    setValue(1)
  }, [])

  return <div>{value}</div>
}

export const WrappedAnonymousComponent = wrap(() => {
  const [value, setValue] = useState(0)

  useEffect(() => {
    // in HOC
    setValue(1)
  }, [])

  return <div>{value}</div>
})

Running pnpm eslint app/ComponentToCheck.ts finds only the use of setValue in the useEffect of DirectComponent:

➜  workspace git:(main) ✗ pnpm eslint app/ComponentToCheck.ts

> nextjs@0.1.0 eslint /project/workspace
> eslint "app/ComponentToCheck.ts"


/project/workspace/app/ComponentToCheck.ts
  10:5  error  Error: Calling setState synchronously within an effect can trigger cascading renders

Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
* Update external systems with the latest state from React.
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.

Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).

/project/workspace/app/ComponentToCheck.ts:10:5
   8 |   useEffect(() => {
   9 |     // Direct
> 10 |     setValue(1)
     |     ^^^^^^^^ Avoid calling setState() directly within an effect
  11 |   }, [])
  12 |
  13 |   return <div>{value}</div>  react-hooks/set-state-in-effect

✖ 1 problem (1 error, 0 warnings)

 ELIFECYCLE  Command failed with exit code 1.

Expected behavior

Running pnpm eslint app/ComponentToCheck.ts should also detect the use of setValue in the useEffect within the WrappedAnonymousComponent.

How often does this bug happen?

Every time

DevTools package (automated)

No response

DevTools version (automated)

No response

Error message (automated)

No response

Error call stack (automated)


Error component stack (automated)


GitHub query string (automated)


Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions