What kind of issue is this?
Link to repro
https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYhBABQCURwAOsUXIWDkQEYCGMRAvEVDAIAQt2oBtAORcAXpIC6AbgZEiMBDljEAPAD4AEggA2RiABpaXGAF9tAel3LM1kGZDNMaPAHMUIeox2dswAtgAOeEac+IQAshAAJgjIRHQgnCZpDC5uYAAWEADuAJKYOAgwmBlgKDgwUAjWQA
Repro steps
React Compiler changes a quoted computed property access such as object['property'] into object.property. Although these expressions are normally equivalent in JavaScript, they are not equivalent when the output is subsequently processed by Closure Compiler. Closure Compiler treats quoted property accesses as non-renamable, while dot-property accesses may be renamed.
For example:
function Foo() {
const namespace = useParams()['namespace'];
return <>Hello, {namespace}</>;
}
is compiled to:
import { c as _c } from "react/compiler-runtime";
function Foo() {
const $ = _c(2);
const namespace = useParams().namespace;
let t0;
if ($[0] !== namespace) {
t0 = <>Hello, {namespace}</>;
$[0] = namespace;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
In our application, useParams() returns an object whose keys come from React Router’s route parameter strings. Closure Compiler cannot rename those externally produced keys. The authored bracket notation is therefore intentional:
useParams()['namespace'];
After React Compiler changes it to:
Closure may rename namespace, causing the application to read a property that React Router never sets. More generally, React Compiler should avoid rewriting JavaScript syntax when that rewrite is not necessary for a React-specific optimisation. Although object['property'] and object.property usually have the same runtime semantics, other tools in the compilation pipeline may intentionally distinguish between them. Since changing the property-access syntax provides no benefit to React’s memoization output, the compiler should preserve the developer-authored form while still representing the property as statically known internally.
Expected behaviour
React Compiler should preserve the quoted computed-access syntax:
const namespace = useParams()['namespace'];
It can still memoize the resulting value and treat "namespace" as a statically known property internally.
Actual behaviour
The quoted access is emitted as dot notation:
const namespace = useParams().namespace;
Additional context
This is not specific to useParams. Quoted property access is commonly used to identify externally defined or non-renamable property names when compiling with Closure Compiler. The HIR initially represents this syntax as a ComputedLoad. Constant propagation recognises that the key is a constant string and converts it to a PropertyLoad. However, PropertyLoad does not retain whether the original access used bracket notation, and code generation emits string-valued PropertyLoads using dot notation. One possible solution would be to preserve a computed or equivalent syntax flag when promoting a ComputedLoad to a static PropertyLoad. That would allow the compiler to retain its existing analysis and optimisation behaviour while emitting:
instead of:
How often does this bug happen?
Every time
What version of React are you using?
19.2.3
What version of React Compiler are you using?
1.0.0
What kind of issue is this?
Link to repro
https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYhBABQCURwAOsUXIWDkQEYCGMRAvEVDAIAQt2oBtAORcAXpIC6AbgZEiMBDljEAPAD4AEggA2RiABpaXGAF9tAel3LM1kGZDNMaPAHMUIeox2dswAtgAOeEac+IQAshAAJgjIRHQgnCZpDC5uYAAWEADuAJKYOAgwmBlgKDgwUAjWQA
Repro steps
React Compiler changes a quoted computed property access such as
object['property']intoobject.property. Although these expressions are normally equivalent in JavaScript, they are not equivalent when the output is subsequently processed by Closure Compiler. Closure Compiler treats quoted property accesses as non-renamable, while dot-property accesses may be renamed.For example:
is compiled to:
In our application,
useParams()returns an object whose keys come from React Router’s route parameter strings. Closure Compiler cannot rename those externally produced keys. The authored bracket notation is therefore intentional:After React Compiler changes it to:
Closure may rename namespace, causing the application to read a property that React Router never sets. More generally, React Compiler should avoid rewriting JavaScript syntax when that rewrite is not necessary for a React-specific optimisation. Although
object['property']andobject.propertyusually have the same runtime semantics, other tools in the compilation pipeline may intentionally distinguish between them. Since changing the property-access syntax provides no benefit to React’s memoization output, the compiler should preserve the developer-authored form while still representing the property as statically known internally.Expected behaviour
React Compiler should preserve the quoted computed-access syntax:
It can still memoize the resulting value and treat "namespace" as a statically known property internally.
Actual behaviour
The quoted access is emitted as dot notation:
Additional context
This is not specific to
useParams. Quoted property access is commonly used to identify externally defined or non-renamable property names when compiling with Closure Compiler. The HIR initially represents this syntax as aComputedLoad. Constant propagation recognises that the key is a constant string and converts it to aPropertyLoad. However,PropertyLoaddoes not retain whether the original access used bracket notation, and code generation emits string-valuedPropertyLoadsusing dot notation. One possible solution would be to preserve a computed or equivalent syntax flag when promoting a ComputedLoad to a static PropertyLoad. That would allow the compiler to retain its existing analysis and optimisation behaviour while emitting:instead of:
How often does this bug happen?
Every time
What version of React are you using?
19.2.3
What version of React Compiler are you using?
1.0.0