`react/display-name` stops requiring forwardRefs to have `displayName` if function contains an inline condition that returns an object
#3192 opened on Jan 28, 2022
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>
)
})

...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>
)
})

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>
)
})

...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>
)
})

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',