jsx-eslint/eslint-plugin-react

`react/display-name` stops requiring forwardRefs to have `displayName` if function contains an inline condition that returns an object

Open

#3192 opened on Jan 28, 2022

View on GitHub
 (1 comment) (0 reactions) (0 assignees)JavaScript (8,630 stars) (2,797 forks)batch import
bughelp wanted

Description

I have a library with forwardRef components that all have displayName properties. This is usually mandated by the linter; however, a few somehow slipped through without displayName being added, undetected by the linter.

The pattern as to whether the linter would or would not view missing displayName as a problem is very odd. It looks like the pattern is, a forwardRef's return value requires a displayName UNLESS the callback function contains an inline condition (?, &&, ||...) where one or more of the possible values is an object.


Here's a simplified example that (unexpectedly?) does not require a displayName (and contains a ternary that returns an object):

const Example = forwardRef(({ children }, ref) => {
  const props = children ? { testID: 'yes' } : { testID: 'no' }
  return (
    <View {...props} ref={ref}>
      {children}
    </View>
  )
})

image

...and here's an example that (as expected?) does require display name. It's functionally identical, but the ternary returns strings rather than objects, and so doesn't unexpectedly change the linter rule behaviour:

const Example = forwardRef(({ children }, ref) => {
  const props = { testID: children ? 'yes' : 'no' }
  return (
    <View {...props} ref={ref}>
      {children}
    </View>
  )
})

image


Here's another example that does not require display name, this time with && instead of ?:

const Example = forwardRef(({ children }, ref) => {
  const style = children && { backgroundColor: 'blue' }
  return (
    <View style={style} ref={ref}>
      {children}
    </View>
  )
})

image

...and here's a similar example where the && returns a string, not an object, so it does require a display name:

const Example = forwardRef(({ children }, ref) => {
  const testID = children && 'blue'
  return (
    <View testID={testID} ref={ref}>
      {children}
    </View>
  )
})

image


Versions

Tested and confirmed on eslint-plugin-react@7.28.0 (current latest), first seen on eslint-plugin-react@7.23.2.

Project is a yarn 1 monorepo with eslint@7.32.0 (latest 7.x version; yarn why finds only one version each for eslint and eslint-plugin-react).

Screenshots in VSCode 1.63.2 running on MacOS 11.6.1.

Config

The relevant rule is set as:

    'react/display-name': 'error',

Contributor guide