diff --git a/lib/rules/display-name.js b/lib/rules/display-name.js
index ecfeaa7b4f..3c5c847110 100644
--- a/lib/rules/display-name.js
+++ b/lib/rules/display-name.js
@@ -90,13 +90,13 @@ module.exports = {
const namedClass = (
(node.type === 'ClassDeclaration' || node.type === 'ClassExpression') &&
node.id &&
- node.id.name
+ !!node.id.name
);
const namedFunctionDeclaration = (
(node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') &&
node.id &&
- node.id.name
+ !!node.id.name
);
const namedFunctionExpression = (
@@ -202,6 +202,31 @@ module.exports = {
markDisplayNameAsDeclared(node);
},
+ CallExpression(node) {
+ if (!utils.isPragmaComponentWrapper(node)) {
+ return;
+ }
+
+ if (node.arguments.length > 0 && astUtil.isFunctionLikeExpression(node.arguments[0])) {
+ // Skip over React.forwardRef declarations that are embeded within
+ // a React.memo i.e. React.memo(React.forwardRef(/* ... */))
+ // This means that we raise a single error for the call to React.memo
+ // instead of one for React.memo and one for React.forwardRef
+ const isWrappedInAnotherPragma = utils.getPragmaComponentWrapper(node);
+
+ if (
+ !isWrappedInAnotherPragma &&
+ (ignoreTranspilerName || !hasTranspilerName(node.arguments[0]))
+ ) {
+ return;
+ }
+
+ if (components.get(node)) {
+ markDisplayNameAsDeclared(node);
+ }
+ }
+ },
+
'Program:exit': function () {
const list = components.list();
// Report missing display name for all components
diff --git a/tests/lib/rules/display-name.js b/tests/lib/rules/display-name.js
index 0064bc4bc0..9f01354be5 100644
--- a/tests/lib/rules/display-name.js
+++ b/tests/lib/rules/display-name.js
@@ -455,6 +455,22 @@ ruleTester.run('display-name', rule, {
export default React.memo(Component)
`
+ }, {
+ code: `
+ import React from 'react'
+
+ const ComponentWithMemo = React.memo(function Component({ world }) {
+ return
Hello {world}
+ })
+ `
+ }, {
+ code: `
+ import React from 'react'
+
+ const ForwardRefComponentLike = React.forwardRef(function ComponentLike({ world }, ref) {
+ return Hello {world}
+ })
+ `
}, {
code: `
function F() {
@@ -684,6 +700,94 @@ ruleTester.run('display-name', rule, {
errors: [{
message: 'Component definition is missing display name'
}]
+ }, {
+ code: `
+ import React from 'react'
+
+ const ComponentWithMemo = React.memo(({ world }) => {
+ return Hello {world}
+ })
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ code: `
+ import React from 'react'
+
+ const ComponentWithMemo = React.memo(function() {
+ return Hello {world}
+ })
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ code: `
+ import React from 'react'
+
+ const ForwardRefComponentLike = React.forwardRef(({ world }, ref) => {
+ return Hello {world}
+ })
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ code: `
+ import React from 'react'
+
+ const ForwardRefComponentLike = React.forwardRef(function({ world }, ref) {
+ return Hello {world}
+ })
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ // Only trigger an error for the outer React.memo
+ code: `
+ import React from 'react'
+
+ const MemoizedForwardRefComponentLike = React.memo(
+ React.forwardRef(({ world }, ref) => {
+ return Hello {world}
+ })
+ )
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ // Only trigger an error for the outer React.memo
+ code: `
+ import React from 'react'
+
+ const MemoizedForwardRefComponentLike = React.memo(
+ React.forwardRef(function({ world }, ref) {
+ return Hello {world}
+ })
+ )
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
+ }, {
+ // React does not handle the result of forwardRef being passed into memo
+ // ComponentWithMemoAndForwardRef gets shown as Memo(Anonymous)
+ // See https://github.com/facebook/react/issues/16722
+ code: `
+ import React from 'react'
+
+ const MemoizedForwardRefComponentLike = React.memo(
+ React.forwardRef(function ComponentLike({ world }, ref) {
+ return Hello {world}
+ })
+ )
+ `,
+ errors: [{
+ message: 'Component definition is missing display name'
+ }]
}, {
code: `
import React from "react";