Preact: Preact 10.5.x with preact-compat passing both className AND class in props

Created on 24 Sep 2020  路  3Comments  路  Source: preactjs/preact

Reproduction

Next.js with Preact 10.5.2 and preact-compat
https://codesandbox.io/s/strange-smoke-jbhx6?file=/pages/index.js

  "dependencies": {
    "@prefresh/next": "1.2.0",
    "clsx": "1.1.1",
    "next": "latest",
    "preact": "^10.5.2",
    "preact-render-to-string": "5.1.10",
    "react": "github:preact-compat/react#1.0.0",
    "react-dom": "github:preact-compat/react-dom#1.0.0",
    "react-ssr-prepass": "npm:preact-ssr-prepass@^1.0.1"
  },

Steps to reproduce

  1. Component has a default className (default-class)
  2. Component destructures additional className from props ({ className, ...otherProps })
  3. Component merges default className with additional className (clsx("default-class", className))
  4. Remaining props are applied to the component's wrapper element (<div className={clsx("default-class", className} {...otherProps}>...</div>

Expected Behavior

In Preact 10.4.8 there was no problem. In Preact 10.5.2 with preact-compat we are seeing both class and className being passed to the component via props.

Actual Behavior

Our otherProps contains class which gets spread onto the div after className.

The class now only contains ONLY the additional className and not the default className.

My current workaround is to apply className after spreading otherProps.

Most helpful comment

Also experiencing same issue.

Here's a repro:

export default function Home() {
  return (
    <div>
      <MyComponent className="foo" />
      <style>{`
        div { height: 100px }
        .foo { background: red; }
        .bar { background: green; }
      `}</style>
    </div>
  )
}

const MyComponent = ({ className, ...props }) => {
  return <div className={`${className} bar`} {...props} />
}

Expected:

Div to be green

Actual:

Div is red

All 3 comments

Also experiencing same issue.

Here's a repro:

export default function Home() {
  return (
    <div>
      <MyComponent className="foo" />
      <style>{`
        div { height: 100px }
        .foo { background: red; }
        .bar { background: green; }
      `}</style>
    </div>
  )
}

const MyComponent = ({ className, ...props }) => {
  return <div className={`${className} bar`} {...props} />
}

Expected:

Div to be green

Actual:

Div is red

Ahh, sorry this one's on me - I had forgotten about folks relying on className taking precedence over class when spreading props. I'll add these as tests for #2774 to make sure it covers the breakage.

Just published 10.5.3 which includes the fix for this issue :tada:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SabirAmeen picture SabirAmeen  路  3Comments

kay-is picture kay-is  路  3Comments

adriaanwm picture adriaanwm  路  3Comments

matthewmueller picture matthewmueller  路  3Comments

Zashy picture Zashy  路  3Comments