@samitouri / QOS-React / commits / 1bcdd224b1

[compiler] Don't show hint about ref-like naming if we infer another type (#34521)

Some components accept a union of a ref callback function or ref object. In this case we may infer the type as a function due to the presence of invoking the ref callback function. In that case, we currently report a "Hint: name `fooRef` as "ref" or with a "-Ref" suffix..." even though the variable is already named appropriately — the problem is that we inferred a non-ref type. So here we check the type and don't report this hint if we inferred another type.

Joseph Savona committed Sep 18, 2025 at 09:26 UTC 1bcdd224b10999138ef5aa1c1917b28d918e5421
3 files changed +77 -1
compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts
+9 -1
@@ -1816,8 +1816,16 @@ function computeSignatureForInstruction(
1816 }
1817 case 'PropertyStore':
1818 case 'ComputedStore': {
1819 + /**
1820 + * Add a hint about naming as "ref"/"-Ref", but only if we weren't able to infer any
1821 + * type for the object. In some cases the variable may be named like a ref, but is
1822 + * also used as a ref callback such that we infer the type as a function rather than
1823 + * a ref.
1824 + */
1825 const mutationReason: MutationReason | null =
1820 - value.kind === 'PropertyStore' && value.property === 'current'
1826 + value.kind === 'PropertyStore' &&
1827 + value.property === 'current' &&
1828 + value.object.identifier.type.kind === 'Type'
1829 ? {kind: 'AssignCurrentProperty'}
1830 : null;
1831 effects.push({
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-allow-assigning-to-inferred-ref-prop-in-callback.expect.md new
+48
@@ -0,0 +1,48 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @validateRefAccessDuringRender
6 +
7 +function useHook(parentRef) {
8 + // Some components accept a union of "callback" refs and ref objects, which
9 + // we can't currently represent
10 + const elementRef = useRef(null);
11 + const handler = instance => {
12 + elementRef.current = instance;
13 + if (parentRef != null) {
14 + if (typeof parentRef === 'function') {
15 + // This call infers the type of `parentRef` as a function...
16 + parentRef(instance);
17 + } else {
18 + // So this assignment fails since we don't know its a ref
19 + parentRef.current = instance;
20 + }
21 + }
22 + };
23 + return handler;
24 +}
25 +
26 +```
27 +
28 +
29 +## Error
30 +
31 +```
32 +Found 1 error:
33 +
34 +Error: This value cannot be modified
35 +
36 +Modifying component props or hook arguments is not allowed. Consider using a local variable instead.
37 +
38 +error.todo-allow-assigning-to-inferred-ref-prop-in-callback.ts:15:8
39 + 13 | } else {
40 + 14 | // So this assignment fails since we don't know its a ref
41 +> 15 | parentRef.current = instance;
42 + | ^^^^^^^^^ `parentRef` cannot be modified
43 + 16 | }
44 + 17 | }
45 + 18 | };
46 +```
47 +
48 +
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-allow-assigning-to-inferred-ref-prop-in-callback.js new
+20
@@ -0,0 +1,20 @@
1 +// @validateRefAccessDuringRender
2 +
3 +function useHook(parentRef) {
4 + // Some components accept a union of "callback" refs and ref objects, which
5 + // we can't currently represent
6 + const elementRef = useRef(null);
7 + const handler = instance => {
8 + elementRef.current = instance;
9 + if (parentRef != null) {
10 + if (typeof parentRef === 'function') {
11 + // This call infers the type of `parentRef` as a function...
12 + parentRef(instance);
13 + } else {
14 + // So this assignment fails since we don't know its a ref
15 + parentRef.current = instance;
16 + }
17 + }
18 + };
19 + return handler;
20 +}