logoESLint React
Rules

runtime

Enforces JSX runtime related rules including namespace restrictions and deoptimization prevention.

Full Name in eslint-plugin-react-jsx

react-jsx/runtime

Full Name in @eslint-react/eslint-plugin

@eslint-react/jsx-runtime

Presets

recommended recommended-typescript recommended-type-checked strict strict-typescript strict-type-checked

Rule Details

This rule covers two JSX runtime concerns:

  1. no-namespace — React does not support XML namespaced tags (e.g. <ns:Component />). Applies to both classic and automatic runtimes.
  2. no-deoptimization — In the automatic runtime (react-jsx / react-jsxdev), placing key after a spread prop forces the compiler to fall back from _jsx / _jsxs to the slower createElement path.

Common Violations

Using Namespace Tags

XML namespaced tag names (e.g. <ns:Component />) are not supported by React's JSX. Although the JSX specification permits namespaces, React does not implement them. Using a namespaced element will cause a runtime error.

Invalid

// ❌ Namespace tag — not supported by React.
<ns:testcomponent />;
// ❌ PascalCase namespace is also not allowed.
<Ns:TestComponent />;
// ❌ SVG-style namespace is also not allowed.
<svg:circle cx="50" cy="50" r="40" />;

Valid

// ✅ Plain element — no namespace.
<testcomponent />;
// ✅ Member expression — not a namespace.
<object.TestComponent />;
// ✅ PascalCase component.
<TestComponent />;

Placing key After Spread Props (Deoptimization)

When using the automatic JSX runtime (react-jsx / react-jsxdev), the key prop is treated specially by the compiler. If key appears before any spread props, it is passed directly as the key argument of the _jsx / _jsxs / _jsxDev function. If key appears after a spread prop, the compiler falls back to the slower createElement call and passes key as a regular prop, causing a deoptimization. See the Babel REPL and the TypeScript Playground.

Invalid

// ❌ 'key' is after spread — causes deoptimization.
<div {...props} key="1" />;
// ❌ Multiple elements with the same issue.
const App = (props) => {
  return [
    <div {...props} key="1">1</div>,
    <div {...props} key="2">2</div>,
  ];
};
// ❌ Even with other props in between.
<div id="test" {...props} key="1" className="foo" />;

Valid

// ✅ 'key' is before spread — compiler uses the optimized path.
<div key="1" {...props} />;
// ✅ No spread props — no deoptimization concern.
<div key="3" className="" />;
<div className="" key="3" />;
// ✅ Classic runtime annotation — deoptimization check does not apply.
/** @jsxRuntime classic */
<div {...props} key="1" />;

Resources

Further Reading

On this page