Repository: facebook/react
Pull request: Improve lint error messages for useEffectEvent

Called Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and can only be called from the same component.

Called After:

> `logEvent` is a function created with React Hook "useEffectEvent", and can only be called from Effects and Effect Events in the same component.

Referenced Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and can only be called from the same component. They cannot be assigned to variables or passed down.

Referenced After:

> `logEvent` is a function created with React Hook "useEffectEvent", and can only be called from Effects and Effect Events in the same component.  It cannot be assigned to a variable or passed down.

Changed files:
filename: packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
patch: @@ -1637,17 +1637,32 @@ const allTests = {
           const onClick = useEffectEvent(() => {
             showNotification(theme);
           });
+          // error message 1
           const onClick2 = () => { onClick() };
+          // error message 2
           const onClick3 = useCallback(() => onClick(), []);
+          // error message 3
+          const onClick4 = onClick;
           return <>
+            {/** error message 4 */}
+            <Child onClick={onClick}></Child>
             <Child onClick={onClick2}></Child>
             <Child onClick={onClick3}></Child>
           </>;
         }
       `,
+      // Explicitly test error messages here for various cases
       errors: [
-        useEffectEventError('onClick', true),
-        useEffectEventError('onClick', true),
+        `\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
+          'Effects and Effect Events in the same component.',
+        `\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
+          'Effects and Effect Events in the same component.',
+        `\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
+          `Effects and Effect Events in the same component. ` +
+          `It cannot be assigned to a variable or passed down.`,
+        `\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
+          `Effects and Effect Events in the same component. ` +
+          `It cannot be assigned to a variable or passed down.`,
       ],
     },
   ],
@@ -1714,7 +1729,8 @@ function useEffectEventError(fn, called) {
   return {
     message:
       `\`${fn}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
-      `the same component.${called ? '' : ' They cannot be assigned to variables or passed down.'}`,
+      'Effects and Effect Events in the same component.' +
+      (called ? '' : ' It cannot be assigned to a variable or passed down.'),
   };
 }
 

filename: packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts
patch: @@ -166,10 +166,19 @@ function isEffectIdentifier(node: Node, additionalHooks?: RegExp): boolean {
 
   return false;
 }
+
 function isUseEffectEventIdentifier(node: Node): boolean {
   return node.type === 'Identifier' && node.name === 'useEffectEvent';
 }
 
+function useEffectEventError(fn: string, called: boolean): string {
+  return (
+    `\`${fn}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
+    'Effects and Effect Events in the same component.' +
+    (called ? '' : ' It cannot be assigned to a variable or passed down.')
+  );
+}
+
 function isUseIdentifier(node: Node): boolean {
   return isReactFunction(node, 'use');
 }
@@ -769,14 +778,11 @@ const rule = {
         // This identifier resolves to a useEffectEvent function, but isn't being referenced in an
         // effect or another event function. It isn't being called either.
         if (lastEffect == null && useEffectEventFunctions.has(node)) {
-          const message =
-            `\`${getSourceCode().getText(
-              node,
-            )}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
-            'the same component.' +
-            (node.parent.type === 'CallExpression'
-              ? ''
-              : ' They cannot be assigned to variables or passed down.');
+          const message = useEffectEventError(
+            getSourceCode().getText(node),
+            node.parent.type === 'CallExpression',
+          );
+
           context.report({
             node,
             message,