-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What's the reason behind using class instead of className? #103
Comments
Excellent question. To start, Preact is an implementation of the core value behind React - the goal is not to be a perfect drop-in replacement for React, since that would require re-implementing things that the React team has deprecated or moved away from. However, since a "React alternative" is very similar to being an "alternative implementation of React", I put together The decision to use The first point about DOM property parity has actually been mostly discarded as React has evolved. In the latest In addition to these disparities, the semantic meaning of However, if you compare this to React's position on the matter - everyone who learns React+JSX must also understand I think it's admirable that so much thought went into the initial decisions that were made around that time, but I also think it's a good idea to continually revisit decisions as a project evolves. For those who are new to JSX, Finally, I should mention that Preact will happily consume I hope I don't sound too dismissive or opinionated here, this is a discussion I've had with many people over the past few months and I enjoy talking about it. Cheers! |
Wow this is really good explanation and I'm with you about deprecation and unnecessary baggage. Thank you! Also, I think this exactly explanation should be in FAQ part of the website. It's magnificent. |
I'm getting into preact to create my own elements, while still using the libraries out there like : https://github.com/STRML/react-grid-layout which depend on React. Is there a reccomended way to use preact (with its class prop) with preact-compat+React library (with their className prop?) |
@AlexAThomas Preact support both properties. If you prefer Preact intentionally defaults to Preact also ships with object <a class={{ foo:true, bar:false }} /> // equivalent to: <a class="foo" /> Let me know if this answers your question - I know it can be strange to see intentional differences in a library that is otherwise so similar to React, but these are part of the reason Preact exists. It is a library that has no growth baggage, and thus can make decisions that build on a few years of learning in this space. |
If you are just starting out with Preact and writing JSX components, I would recommend you to try to restrict yourself to stateless pure functions as much as you can. They have the exact same API in both libraries and it will very quickly 'force' you into the right mindset. You actually only rarely need state. Here is what a HelloWorld component would look like: // first, make sure the JSX processor is in scope
import { h } from 'preact'
// or, import React from 'react'
// then use JSX as you see fit in a pure stateless component
export default function Greet({greeting='Hello, World!', children, ...props}) {return (
<div {...props}>
<b>{greeting}</b>
{children}
</div>
)}
// use it like so:
var markup = <Greet greeting="Hi there!"><p>How are you doing?</p></Greet> You can even write these components to be 'universal' in the sense that they could be made to work under React and Preact interchangeably, without needing preact-compat or aliasses in webpack etc. This would involve removing the only framework specific code (the import statements) and agreeing on a global name for the JSX processor function and setting that via a |
Small tip to whoever works with IntelliJ (or WebStorm etc.) and gets warned that 'Attribute class is not allowed here': |
@developit That doesn't seem to be true that Babel auto-escapes reserved words. var className = props.class || props.className; |
@developit I take it that support for preact class as objects was later removed. How does one achieve this ? This doesn't work anymore
|
@nojvek That's true, we removed it with the Preact X release as it seemed wrong to have in core. Pretty much all users were using the |
@nojvek maybe you'll find this useful: I work on a project with tight bundle budget (hence choosing Preact 🤓) so I use my own version of utils: export const classNames = classArr => classArr.filter(el => el).join(' ') // filter falsy values someComponent: <div className={classNames(['always', isSpecialCase && 'special'])}> |
Ah sweet. That works. Coming from snabbdom the class object notation is natively supported and they use .classList property for diffing which is a set under hood so faster than setting the class attributes on the dom nodes. I’m hoping preact also uses classList properly rather than class attribute on the underlying dom nodes. |
@nojvek That's very unlikey that we'll switch to // First render
<div class="foo bar bob baz" />
// second render
<div class="bar baz" /> Right now this is just a property setter: dom.className = "bar baz" If we would switch to use // First render
<div class={{ foo: true, bar: true }} />
// Second render, shape changed
<div class={{ foo: true }} /> In the above example we don't know if a class was removed right away. We'd need to manually iterate over the old object and check if the property is not present in the new class object. The only scenario in which this is more performent would be this one: // First render
<div class={{ foo: true, bar: true }} />
// Second render, shape stays the same
<div class={{ foo: true, bar: false }} /> |
Thanks for the explanation 👍 I just stumbled into this because Preact internally rewrites const { class, ...linkProps } = props;
<Link {...linkProps} /> which I needed because the Next.js Link component doesn't accept Facebook also thought about this transition and dropped it exactly because of these issues with |
Interesting. Can you open a new issue with a full reproduction so we can investigate and triage? |
@DominikGuzei var props = { 'class': 'test', some: 'other' }
var { ...linkProps } = props // shallow copy
delete linkProps['class'] // ugly but works
console.info(linkProps) // {some: "other"} |
+1 on the destructure bit. So Preact adds both
Did I miss something? Again, I can't believe this hasn't caused issues for me yet (maybe it has) |
@ansonatloop No, the inner We had a regression in |
@marvinhagemeister Hmm, well, I am on a slightly older version (10.4.7) and with https://github.com/preactjs/preact/blob/10.4.7/compat/src/render.js#L108 see: But nonetheless, you're probably referring to a version in which the above is no longer true. I see #2772 might be related and after bumping to |
Actually this is easy to fix by assigning the property to a different variable name when destructuring: const { class: className, ...linkProps } = props;
<Link {...linkProps} /> |
@rejc2 Oooh nice one! I never thought about that but it's sure a lot cleaner to do it like that 👍 |
I've been thinking, why class but not className? If I'm not mistaken, className in react used due to Element.className and not Element.class. Why class here? If suddenly someone would try to switch-and-go to react or similar, he will experience huge compatibility issues.
Or there is no goal in the end - for preact to be total drop-in-replacement but to be something new?
The text was updated successfully, but these errors were encountered: