jsx-no-new-object-as-prop
Disallow render-local object allocations passed through JSX props.
Deprecated
- Lifecycle: Deprecated, frozen, and non-recommended.
- Deprecated since:
v3.0.0 - Available until:
v4.0.0 - Use instead:
no-unstable-react-values
The replacement consolidates JSX, function, array, and object prop stability checks behind one rule and one intrinsic-element policy. Do not enable both.
Targeted pattern scope
This rule reports object literals and unshadowed Object() or new Object() allocations used as JSX prop values inside a function or class render scope. Object calls are reported only when they have no argument or a statically primitive argument; an unknown or object-valued argument may be returned unchanged. The rule follows logical and conditional branches and resolves a single same-function const initializer.
Module constants and mutable bindings are not traced. Intrinsic JSX attributes can be exempted by name; custom-component props remain in scope.
What this rule reports
A fresh object reference can defeat shallow prop comparisons or retrigger identity-sensitive consumers. Creating an object during render is otherwise ordinary JavaScript and is not automatically a defect.
Why this rule exists
Object identity is observable by shallow comparisons, dependency arrays, and some component APIs. The rule highlights new identities where a project has chosen to make that cost explicit.
❌ Incorrect
function Card() {
return <Panel options={{ dense: true }} />; // New object identity every render.
}
function Card() {
const options = { dense: true };
return <Panel options={options} />; // The local const does not make it stable.
}
✅ Correct
const panelOptions = { dense: true };
function Card() {
return <Panel options={panelOptions} />;
}
function Card({ options }: { options: PanelOptions }) {
return <Panel options={options} />;
}
Behavior and migration notes
This rule reports only. Hoisting an object or adding useMemo can be wrong when its properties depend on render inputs.
React Compiler can automatically memoize values and components in supported builds. Enable this opt-in rule only for boundaries where stable identity is intentional and measured. It is included by both the all and allStrict presets.
Options
interface Options {
nativeAllowList?: "all" | readonly string[];
}
Default: { nativeAllowList: "all" }
nativeAllowList ignores case-insensitive attribute names on intrinsic JSX elements. The default "all" keeps the rule focused on component props because intrinsic attributes do not participate in a child component's prop-identity contract. Set it to [] to check every intrinsic attribute, or provide selected names to ignore.
// config: { nativeAllowList: ["style"] }
function Card() {
return <section style={{ display: "grid" }} />; // Allowed intrinsic attribute.
}
ESLint flat config example
import etcMisc from "eslint-plugin-etc-misc";
export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/jsx-no-new-object-as-prop": "warn",
},
},
];
When not to use it
Disable this rule when consumers do not rely on prop identity, when inline objects improve clarity without measured cost, or when React Compiler owns memoization.
Package documentation
The rule is a clean-room implementation informed by eslint-plugin-react-perf. This implementation does not generate memoization fixes.
Rule catalog ID: R019
Further reading
Adoption resources
- Start at warning level in CI, then move to error after cleanup.
- Review whether stable identity is observable before lifting or memoizing values.