fixhunt

biome suspicious/noReactSpecificProps

labelled safe
Runs / 2026-10-17T21-12-31-217Z-qon6-biome-suspicious_noReactSpecificPropsbiome 2.5.152026-10-17 21:12 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 8 rejectedmodel cost $0.0036

Analysis Nemotron 3 Super

The rule flags any JSX attribute named 'className' as a React-specific prop that should be replaced with 'class'.

Fix: Replace every occurrence of the JSX attribute name 'className' with 'class', preserving the attribute's original value (including expressions, strings, or JSX spread) and all other attributes, whitespace, and formatting.

8 hazards
  • Rewriting 'className' to 'class' in a JSX element that is actually a React component will cause the prop to be ignored, breaking styling or behavior that relies on the React-specific prop.
  • If the JSX element is part of a higher-order component or factory that expects a 'className' prop internally (e.g., for forwarding), renaming it to 'class' will prevent the prop from being received, leading to missing styles or logic.
  • In frameworks like Solid or Qwik, if a component uses 'className' as a local variable or state alias (e.g., via destructuring), the rewrite could incorrectly attribute the JSX attribute to a variable scope, causing a reference error.
  • When 'className' is used with a spread operator (e.g., <div {...props} className="extra" />), the fix only renames the explicit attribute; however, if props contains a 'className' field, the spread may still pass it through, resulting in duplicate or conflicting attributes depending on the framework's attribute merging behavior.
  • If the JSX appears inside a string literal, template literal, or JS comment (e.g., const msg = '<div className="box"></div>'; or {/* <div className="box" /> */}), the tool must not modify it, but a flawed implementation might erroneously rewrite the text, corrupting the string or comment content.
  • If the 'className' attribute contains a value with side effects (e.g., className={getClass()}), the rewrite preserves the value, but if the framework treats 'class' differently (e.g., as a signal or reactive property), the timing or tracking of the side effect may change.
  • In SVG elements, while 'class' is valid, some older SVG parsers or tools might expect 'className' for compatibility; renaming to 'class' could break tooling or CSS selector matching in edge cases involving SVG-specific CSSOM access.
  • If the JSX element is dynamically generated via a function that returns a string containing 'className' (e.g., return `<div className="${cls}">`;), the rule does not apply because it's not JSX, but if misapplied, it would corrupt the template string.

Programs

idresulttitlehazard
r1-p001invalidSolid/Qwik-like component using className as local variableIn frameworks like Solid or Qwik, if a component uses 'className' as a local variable or state alias (e.g., via destructuring), the rewrite could incorrectly attribute the JSX attribute to a variable
r1-p002invalidTemporal Dead Zone due to hoisting before declarationtemporal dead zone after code is hoisted or reordered
r1-p003silent prediction offSVG element relying on className for legacy tooling/CSSOMIn SVG elements, while 'class' is valid, some older SVG parsers or tools might expect 'className' for compatibility; renaming to 'class' could break tooling or CSS selector matching in edge cases invo
r1-p004invalidArguments object and rest parameters interactionarguments object, function.length, default parameters, rest parameters
r1-p005invalidVar hoisting and re-declaration in loopvar hoisting and re-declaration inside loops or after use
r1-p006invalidSpread operator with conflicting className in propsWhen 'className' is used with a spread operator (e.g., <div {...props} className='extra' />), the fix only renames the explicit attribute; however, if props contains a 'className' field, the spread ma
r1-p007invalidJSX element that is actually a React component ignoring class propRewriting 'className' to 'class' in a JSX element that is actually a React component will cause the prop to be ignored, breaking styling or behavior that relies on the React-specific prop.
r1-p008invalidComments attached to the className attributecomments attached to the removed or moved code
r2-p001invalidSpread operator with conflicting className in propsWhen 'className' is used with a spread operator (e.g., <div {...props} className="extra" />), the fix only renames the explicit attribute; however, if props contains a 'className' field, the spread ma
r2-p002silent prediction offFunction declarations inside blocks, switch cases, labeled statementsfunction declarations inside blocks, switch cases, labeled statements
r2-p003silent prediction offTemporal dead zone after code is hoisted or reorderedtemporal dead zone after code is hoisted or reordered
r2-p004silent prediction offArguments object, function.length, default parameters, rest parametersarguments object, function.length, default parameters, rest parameters
r2-p005silent prediction offOrder of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)order of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
r2-p006silent prediction offNull/undefined distinction, optional chaining short-circuit, nullish vs falsynull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r2-p007silent prediction offLabel/break/continue control flow, finally blocks, early returns in nested blockslabel/break/continue control flow, finally blocks, early returns in nested blocks
r2-p008silent prediction offVar hoisting and re-declaration inside loops or after usevar hoisting and re-declaration inside loops or after use

Sources

r1-p001 · Solid/Qwik-like component using className as local variable (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1function Component() {
2 const { className } = {};
3 return <div className={className || 'default'}></div>;
4}
5console.log(typeof Component);
r1-p002 · Temporal Dead Zone due to hoisting before declaration (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1(() => {
2 try { console.log(<div className={x}></div>); } catch (e) { console.log(e.name + ': ' + e.message); }
3 let x = 'hi';
4})();
r1-p003 · SVG element relying on className for legacy tooling/CSSOM
1const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
2svg.setAttribute('className', 'test'); // sets attribute
3console.log(svg.getAttribute('class'));
4// After fix: becomes <svg class="test" ...> -> getAttribute('class') returns null because attribute is now 'class'
5// But we simulate by checking what the parser sees:
6console.log(svg.hasAttribute('className')); // false after fix? Actually we set className manually.
7// Instead, show that accessing .className property on SVGElement returns string (reflects class)
8console.log(typeof svg.className);
r1-p004 · Arguments object and rest parameters interaction (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1function test(a, b = () => <div className={a}></div>, ...rest) {
2 console.log(arguments.length, rest.length);
3 return b();
4}
5test(1);
r1-p005 · Var hoisting and re-declaration in loop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1for (var i = 0; i < 2; i++) {
2 var className = i === 0 ? 'first' : 'second';
3 console.log(<div className={className}></div>);
4}
r1-p006 · Spread operator with conflicting className in props (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1const props = { className: 'spread', id: 'x' };
2const el = <div {...props} className='explicit' />;
3console.log(el.props.className); // In React, later wins -> 'explicit'
4// After fix: becomes <div {...props} class='explicit' /> but props.className still spreads -> two attributes
5// We can't render, so show that props has className and we spread it
6console.log('props has className:', !!props.className);
r1-p007 · JSX element that is actually a React component ignoring class prop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1const Button = ({ className, children }) => {
2 return <button className={className}>{children}</button>;
3};
4const el = <Button className='btn'>hi</Button>;
5console.log(el.props.className); // Should be 'btn'
6// After fix: becomes <Button class='btn' ...> -> React component ignores 'class' prop, so className becomes undefined
7console.log('After fix simulation:', (<Button class='btn' />).props.className);
r1-p008 · Comments attached to the className attribute (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1/* comment before */
2const x = <div
3 /* className comment */
4 className='test'
5 /* another */
6/>;
7/* comment after */
8console.log(typeof x);
r2-p001 · Spread operator with conflicting className in props (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-12-3)
1// Hazard 1: Spread operator with conflicting className
2const props = { className: "spread-class", id: "test" };
3function render() {
4 return `<div ${{"{...props}"}} className="explicit-class">content</div>`;
5}
6console.log(render());
r2-p002 · Function declarations inside blocks, switch cases, labeled statements
1// Hazard 2: Function declarations inside blocks
2if (true) {
3 function getClassName() { return "block-fn"; }
4 const div = `<div className=${getClassName()}></div>`;
5 console.log(div);
6}
7// After fix: className -> class, but function scope remains
8try { console.log(typeof getClassName); } catch(e) { console.log(e.name); }
<div className=block-fn></div>
undefined
r2-p003 · Temporal dead zone after code is hoisted or reordered
1// Hazard 3: Temporal dead zone
2console.log(typeof classNameVar); // TDZ
3let classNameVar = "tdz-value";
4const el = `<div className=${classNameVar}></div>`;
5console.log(el);
6// Fix changes attribute but TDZ error occurs before
r2-p004 · Arguments object, function.length, default parameters, rest parameters
1// Hazard 4: Arguments and rest parameters
2function testFn(a, b = getDefault(), ...rest) {
3 function getDefault() { return "default"; }
4 const attrs = rest.length ? `{...rest}` : "";
5 return `<div className=${a || "fallback"} ${attrs}></div>`;
6}
7console.log(testFn("arg1", undefined, { className: "rest-class" }));
r2-p005 · Order of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
1// Hazard 5: Order of evaluation with side effects
2let counter = 0;
3function inc() { return ++counter; }
4const value = inc(); // side effect: counter=1
5const el = `<div className="${value}-${inc()}"></div>`; // inc() called again: counter=2
6console.log(el, `counter=${counter}`);
7// Fix: attribute name change doesn't affect eval order
<div className="1-2"></div> counter=2
r2-p006 · Null/undefined distinction, optional chaining short-circuit, nullish vs falsy
1// Hazard 6: Null/undefined and optional chaining
2const obj = { className: null };
3const val = obj.className ?? "fallback";
4const el = `<div className=${val}></div>`;
5console.log(el);
6// After fix: class -> but val is still "fallback"
7console.log(obj.className === null ? "is null" : "has value");
<div className=fallback></div>
is null
r2-p007 · Label/break/continue control flow, finally blocks, early returns in nested blocks
1// Hazard 7: Label/break/continue
2outer: {
3 for (let i = 0; i < 2; i++) {
4 if (i === 1) break outer;
5 const el = `<div className="loop-${i}"></div>`;
6 console.log(el);
7 }
8}
9console.log("after break");
10// Fix runs but break skips second iteration
<div className="loop-0"></div>
after break
r2-p008 · Var hoisting and re-declaration inside loops or after use
1// Hazard 8: Var hoisting and re-declaration
2for (var i = 0; i < 2; i++) {
3 var className = `iter-${i}`; // hoisted, re-declared
4 console.log(`i=${i}, className=${className}`);
5 const el = `<div className=${className}></div>`;
6 console.log(el);
7}
8console.log(`final: className=${className}`); // last value
i=0, className=iter-0
<div className=iter-0></div>
i=1, className=iter-1
<div className=iter-1></div>
final: className=iter-1