facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
229.88k stars 47.07k forks source link

React Fire: Modernizing React DOM #13525

Closed gaearon closed 4 years ago

gaearon commented 6 years ago

For latest status, see an update from June 5th, 2019: https://github.com/facebook/react/issues/13525#issuecomment-499196939


This year, the React team has mostly been focused on fundamental improvements to React.

As this work is getting closer to completion, we're starting to think of what the next major releases of React DOM should look like. There are quite a few known problems, and some of them are hard or impossible to fix without bigger internal changes.

We want to undo past mistakes that caused countless follow-up fixes and created much technical debt. We also want to remove some of the abstraction in the event system which has been virtually untouched since the first days of React, and is a source of much complexity and bundle size.

We're calling this effort "React Fire".

πŸ”₯ React Fire

React Fire is an effort to modernize React DOM. Our goal is to make React better aligned with how the DOM works, revisit some controversial past decisions that led to problems, and make React smaller and faster.

We want to ship this set of changes in a future React major release because some of them will unfortunately be breaking. Nevertheless, we think they're worth it. And we have more than 50 thousands components at Facebook to keep us honest about our migration strategy. We can't afford to rewrite product code except a few targeted fixes or automated codemods.

Strategy

There are a few different things that make up our current plan. We might add or remove something but here's the thinking so far:

Tradeoffs

Rollout Plan

At this stage, the project is very exploratory. We don't know for sure if all of the above things will pan out. Because the changes are significant, we will need to dogfood them at Facebook, and try them out in a gradual fashion. This means we'll introduce a feature flag, fork some of the code, and keep it enabled at Facebook for a small group of people. The open source 16.x releases will keep the old behavior, but on master you will be able to run it with the feature flag on.

I plan to work on the project myself for the most part, but I would very much appreciate more discussion and contributions from @nhunzaker, @aweary, @jquense, and @philipp-spiess who have been stellar collaborators and have largely steered React DOM while we were working on Fiber. If there's some area you're particularly interested in, please let me know and we'll work it out.

There are likely things that I missed in this plan. I'm very open to feedback, and I hope this writeup is helpful.

tcodes0 commented 6 years ago

It's nice to see steady development on such a good library like React. πŸŽ‰ class will make the usability much better, it's worth it imo

justinfagnani commented 6 years ago

@gaearon

custom and normal elements are completely separate code paths

That itself seems like something to fix too. Is there any reason not to treat all elements the same? That's the intention of the HTML and DOM specs.

gaearon commented 6 years ago

@justinfagnani As discussed previously, the reason we didn't do it at the time was because there was no convention for how to tell whether to set a property or an attribute β€” and there was a risk that by using a check we risk making it impossible for web platform to add new properties to the prototype. I think by now there's already some sort of consensus in the RFCs and PRs that @robdodson has been working on, and we can probably pick it up from there.

justinsoong commented 6 years ago

πŸ‘ πŸ”₯ πŸ”₯ πŸ”₯

trueadm commented 6 years ago

React Fire should also allow us to apply some of the clever performance optimizations that Inferno has – but haven't been able to apply because of breaking changes. Exciting times :)

CarlosLCervantes commented 6 years ago

LGTM

ggreer commented 6 years ago

Related to the proposed className -> class rename: I'd love a classes property that took an array of strings. That would save me the trouble of a lot of string manipulation (or the use of classnames) in my components.

I think the only disadvantage of a classes prop would be that arrays containing the same strings in the same order would cause a re-render in pure component, while a string of the same CSS classes wouldn't. Honestly though, it seems like a minor issue. I think most React devs already know the tradeoffs of arrays & objects in props.

renatoagds commented 6 years ago

@gaearon have plans for backward compatibility? Maybe follow the same path as React Fiber, adding warnings about the changes and giving time for large codebases update that without losing new updates.

AlexGalays commented 6 years ago

https://www.youtube.com/watch?v=F1U0qvtQnE8

gaearon commented 6 years ago

Regarding class and className.

I know we won't get a broad agreement on this whichever way we go. People have really strong opinions about this one. I want to share how I'm thinking about it, in a hope that it will be helpful.

Component API Should Feel Idiomatic

There is a common argument that React "matches JavaScript" and thus className is preferred. I think this assertion is subtly misunderstood so I'd like to focus on it a little.

In React, first and foremost, we care that using a React component should feel like idiomatic JavaScript. This means that if I use a hypothetical <Table> component, I expect its props to be camelCase:

<Table
  rowHeight={10}
  headerBorderInset={5}
  renderRow={this.renderRow}
/>

I don't expect to see prop names like row_height or row-height in a component's public API. Component's props are an object (kind of like an "option bag"), and we generally expect those options to be camelCase. This may not be always idiomatic in DOM, but the DOM is not very consistent in many places. React aligns with the JavaScript ecosystem which overwhelmingly uses camelCase.

But what about the DOM? This is where it gets thorny.

DOM Properties Are Not Just "Attributes in JS"

In DOM, we have attributes and properties. Attributes are the things you usually see in HTML. Properties are the things you usually set from JS. But crucially, DOM APIs exist both for setting properties and for setting attributes β€” and they're not even always setting the same thing.

node.value = 10; // setting a property
node.setAttribute('value', '10'); // setting an attribute

In many cases it doesn't matter. In some cases it does. But maybe not in the way one might think from using React (which has one abstraction over both).

React Is Not Just Setting Properties

A common misconception is that since React currently uses the camelCase convention for most DOM props, it means React is setting DOM properties. This is wrong.

In fact, React is currently using attributes for almost all props it supports. In some cases, like value, this is causing issues (which as I discussed we want to revert). In other cases, this is actually great β€” because we don't have to include a list of supported properties into the React bundle. Using attributes under the hood is what allowed a major size reduction in React 16.

My point here is that whether React uses properties or attributes internally is an implementation detail β€” and has nothing to do with whether React DOM element API should be using property names, attribute names, or even some other names that make sense.

Still, Let's Just Use Property Names?

Okay, properties and attributes are an implementation detail. But why not just standardize on using DOM property names since those were specifically made "for JavaScript"? Isn't that how React API is designed today?

Well, not quite. Only one of the props enumerated below corresponds to a real DOM object property:

<div
  tabIndex={1}
  data-id="123"
  aria-live="polite"
  nopin="nopin"
  itemType="http://schema.org/Movie"
  onClick={function() { alert('hi') }}
/>

Ironically, the only prop above that has an actual DOM property with the same name corresponding to it (tabIndex if you weren't sure) is actually being set by React as an attribute!

So by this point you probably see it's neither clear-cut nor consistent. In some cases properties don't exist (such as for custom, non-standard attributes), in some cases React could provide a richer API (data- vs dataSet) but currently doesn't.

In some cases React intentionally chooses to deviate (onClick in React vs onclick DOM property) because it makes more sense for custom React components. This is because React components often expose more complex event handlers like onItemClick. It would be very inconsistent if you wrote <Button onclick> but <Table onItemClick>. And <Table onitemclick> isn't camelCase, which we wanted to avoid in a component API.

Above, I explained that React already isn't consistent about "always using DOM property name", that React doesn't even actually use properties internally (so that rule of thumb doesn't describe the actual mechanics either), and that in many cases DOM properties simply don't exist so we have to stick with allowing the attribute name.

If Not Property Names, Let's Be Consistent and Use Attribute Names?

So why not go with using only attribute names? This could be plausible. But now we bump into the very first consideration we brought up. Using a React component should feel like idiomatic JavaScript. But often components forward at least some props to the underlying DOM element.

<Button
  borderColor='red'
  tabIndex={1}
 />

 // renders...

 <button
   tabIndex={1}
/>

It would be awkward for a custom Button to accept props with inconsistent capitalization:

<Button
  borderColor='red'
  tabindex={1}
 />

This forces the consumer to always remember if a certain prop is an actual DOM prop, or just a part of the component contract. Even that distinction is fuzzy β€” a component may choose to first pass a certain prop through, but then to actually start using it for some extra logic. Where do you put the boundary between "DOM props" and "other props"?

I think this is the primary reason it's desirable for props like tabIndex, cellSpacing, and most other DOM-related props to follow the camelCase convention. It's not because they're DOM property names. It's because they often end up in component APIs. And we want component APIs to be consistently camelCase.

We want to make it easy for custom components like Button to wrap and forward them without either "translating" them to the attribute name at the point where they flow into the DOM, and without introducing non-camelCase props into a custom component API.

This also explains why props like data-*, aria-*, and custom attributes are reasonable exceptions (even though we could make richer APIs for them). They are rarely passed to custom components. Typically, they are too coupled to the DOM to be useful in custom components β€” and instead, they become an implementation detail of something like a <Modal> or a <Button> with a richer camelCase API.

React Properties Already Don't Match DOM Properties

If the "DOM property name" convention didn't work out, we need something else. What is it? Could it be "camelCase version of the attribute name"? It seems like this almost always already checks out.

If this sounds too radical, consider that we're already doing this. We support something called srcSet. But the DOM property name for it is srcset. We have autoCapitalize but the DOM property is called autocapitalize. We have autoFocus but the DOM property is autofocus.

We are already deviating from DOM property names when they don't match the camelCase JavaScript convention. Which brings us to class.

Finally: className vs class

Part of the original justification for making it className was because React was setting DOM properties, and className is the name of the DOM property.

However, as I explained above, React doesn't use properties anymore except three or four special case. More importantly, React doesn't even consistently use DOM property names β€” rather, it uses names that would look natural when used from JavaScript, regardless of internal naming inconsistency in either DOM attribute and property names. And that is because React cares most about keeping prop names for custom components feel "JavaScripty". In this sense, tabindex is not "JavaScripty" β€” but both class and className are.

Another argument against class early on was that code like this wasn't valid ES3 (relevant for IE8):

// Not valid in ES3
// Valid in ES5
var props = { class: 'foo' };

But most don't write ES3 anymore. Either you're using a toolchain like Babel or you're likely targeting IE9+ β€” React doesn't even support IE8 now.

So the only inconvenience left with class is that you can't write this:

// Not valid at all :-(
const class = props.class;
const { class } = props;

But I think that with time, this argument is not strong enough by itself. React doesn't force you to use destructuring or using this specific variable name, and writing something like

// Valid
const {class: cls} = foo;
const cls = props.class;

isn't that much more effort.

Typically people pass class down far more often than read it because many components contain more than one inner <div> or other host elements. So you end up writing <div className> much more often than wanting to destructure class. And thus the change to class would save more keyboard typing than it would introduce.

There is another important point here.

Passing class down through many levels is not a great pattern by itself. It's necessary for libraries, but in application code it often leads to fragile components. The ones whose styles break all the time because there's a hundred different callsites each appending a different class, causing cascade bugs. So it's not clear how valuable it is to encourage destructuring class in the first place. I think it's fine that you need to write one more line of code to read it from props (or you can just use props.class and not think about it).

If you are writing a component that is very close to the DOM (and thus it makes sense for it to take class as a prop), you likely want to forward other props too. So you can use rest syntax in destructuring:

// Valid in ES2018

function Button({ color, ...rest }) {
  const buttonClass = rest.class +  ' Button-' + color;
  return <button {...rest} class={buttonClass} />
}

And if you didn't need to modify it then you could've just forwarded {...rest} without even reading class from it. So the destructuring limitation might help encourage better component design.

Why Not Both?

why not both

Finally, can't we just support both class and className? In a way, we already do, but React yells at you for it with a warning. There is a reason for this.

If we support both without warnings, then the community will split over which one to use. Each component on npm that accepts a class prop will have to remember to forward both. If even one component in the middle doesn't play along and implements only one prop, the class gets lost β€” or you risk ending up with class and className at the bottom "disagreeing" with each other, with no way for React to resolve that conflict. So we think that would be worse than status quo, and want to avoid this.

Summary

If React was open sourced today, it seems like the pros of allowing class (closer conceptually to what most people expect, less typing for the most commonly used prop) outweigh the downsides (slightly more typing to intercept it β€” in which cases you'll probably just want the spread operator anyway).

What we used to see as downsides (inconsistent with DOM properties) is moot because we neither set DOM properties anymore, nor even strive to be consistent with them. Instead we're aiming to have an attribute-based but camelCase API on the consuming side of React components β€” which we're already almost consistent at. And class="Button" is clearly more convenient than className="Button". In fact if DOM API was designed today it would probably let you set .class property precisely because the restriction on using class in an assignment like this was lifted in ES5 β€” almost ten years ago.

The only remaining big downside is the migration cost. We'll assess this carefully. But if we're doing a bunch of changes anyway, we might be able to make this one too and fix it for good. We're not thinking about this lightly and we take all your concerns into consideration.

Note: this might make sense to do for other React prop names that don't match camelCased attribute names. I'm thinking of htmlFor.

gaearon commented 6 years ago

@renatoagds

have plans for backward compatibility? Maybe follow the same path as React Fiber, adding warnings about the changes and giving time for large codebases update.

As I noted:

And we have more than 50 thousands components at Facebook to keep us honest about our migration strategy. We can't afford to rewrite product code except a few targeted fixes or automated codemods.

So we'll definitely try to make migration strategy as smooth as possible, just like we always do. If it's not smooth we won't be able to make the change ourselves.

sbrichardson commented 6 years ago

re: className -> class, I'm cool with whichever decision, I can definitely see the exception to changing class for new users, and a side benefit of shorter lines of code. Although, they would still need to learn about the other camelCase names.

jamesplease commented 6 years ago

So the only inconvenience left with class is that you can't write this:

const { class } = props;

But I think that with time, this argument is not strong enough by itself. React doesn't force you to use > destructuring, and writing

const class = props.class;

isn't that much more effort.

Two (possibly small) things:

  1. Isn't const class = props.class invalid JavaScript? I didn't think that it was, and in a quick test Chrome doesn't like it. Also, this article suggests that it is not valid.

  2. I could see this change being a (once again, potentially small) area of frustration for folks that write components like this: nvm (see Update below)

const { oneProp, twoProp, className, ...rest }  = this.props;

// do stuff with oneProp, twoProp, className

return (
  <div
    someProp={prop}
    anotherProp={anotherProp}
    className={someClassName}
    {...rest}/>
);

After this change, this would need to be something like...

const { oneProp, twoProp, ...rest }  = this.props;

// do stuff with oneProp, twoProp, this.props.className

return (
  <div
    someProp={prop}
    anotherProp={anotherProp}
    {...rest}
    class={someClassName}/>
);

It's not impossible to work around this change, but it is a little bit more to keep in mind when both writing and reading components in this style.

Update:

Nevermind,

const { class: className } = this.props;

does the trick.

milesj commented 6 years ago

The only remaining big downside is the migration cost. We'll assess this carefully. But if we're doing a bunch of changes anyway, we might be able to make this one too and fix it for good. We're not thinking about this lightly and we take all your concerns into consideration.

Luckily this is easily mitigated if one is using a CSS-in-JS approach, like Aesthetic. Thanks for the amazing write up!

sbrichardson commented 6 years ago

Random tip regarding attribute names, I found the excellent project, svg2jsx is great for converting large SVGs to use in React!

gaearon commented 6 years ago

@jamesplease Sorry, my mind blanked β€” you're right. Edited.

sbrichardson commented 6 years ago

@jamesplease you are right. That also comes up frequently working with JSON, for the default value, so annoying!

const { default: defaultVal } = property
HelveticaScenario commented 6 years ago

While you're changing the event system, it would be really nice to see something similar to Inferno's linkEvent function so we can do event handling using props in functional components without having to create an anonymous function each render.

sompylasar commented 6 years ago

className -> class will be a huge change for the ecosystem, numerous unmaintained components will become incompatible, and there will be nothing you can do if you cannot patch them. Maybe have some wrapper like StrictMode that disables this change for the components deeper in the tree to provide a gradual migration path?

gaearon commented 6 years ago

I could see this change being a (once again, potentially small) area of frustration for folks that write components like this:

const { oneProp, twoProp, className, ...rest }  = this.props;

// do stuff with oneProp, twoProp, className

return (
 <div className={someClassName} {...rest}/>
);

Just don't destructure it.

const { oneProp, twoProp, ...rest }  = this.props;

return (
  <div
    {...rest}
    class={'something ' + rest.class}
  />
);
justinfagnani commented 6 years ago

@gaearon

whether React uses properties or attributes internally is an implementation detail

That seems like a problem too, honestly. DOM elements can and do behave differently in some cases depending on whether you're setting attributes or properties. React can't possibly know about all of the differences, but users of elements can know about the elements that they use. Explicit control over properties, attributes and events would let authors break out of this situation.

gaearon commented 6 years ago

@justinfagnani If you have specific things you'd like us to change, do you mind filing a separate issue with an API you suggest? This sounds a bit out of scope of this issue.

gaearon commented 6 years ago

@sompylasar

className -> class will be a huge change for the ecosystem, numerous unmaintained components will become incompatible, and there will be nothing you can do if you cannot patch them. Maybe have some wrapper like StrictMode that disables this change for the components deeper in the tree to provide a gradual migration path?

I agree β€” and we're still weighing pros and cons. Nothing is finalized.

But in practice, the problem of unmaintained components is not new β€” it comes up every React major release because something changes in majors by defintion (we can't move forward otherwise, and we don't have the luxury of keeping all legacy code in the bundle forever unlike in e.g. server environments). The same problem came up when PropTypes moved into a separate package, and will happen again with the UNSAFE_ lifecycle renaming. Unmaintained packages get forked or patched. We realize it's a big time sink, and this is why we avoid doing more than one big major in a year. For folks who can't afford to help, typically waiting a few months before moving to a new major is the best strategy because early adopters pave the way and revive the abandoned packages. Then we move forward all together.

Again β€” I very much understand your hesitation, but this is not principally different from other breaking changes that happened in the past, or that might happen in the future. As always, we'll put a lot of effort and emphasis on automated scripts you can run to convert most of your codebase, and that you can run on other packages as well (and send PRs to them β€” or fork them in their last state).

sompylasar commented 6 years ago

Regardless of your decision, one more argument against class is searchability. How many false positives will give you searching by class when you wanted to find components that use CSS classes in ES6 code that uses JS class components? Yes, you can search for class={, but what about destructuring of props in JSX that are created as an object in JS? (I'm against heavy use of props destructuring but they are still used) Of course, we need better context-aware AST-based search tools in code editors, but for now we only have text and regexp. Of course type systems may help to track object passing, but large population hasn't adopted them.

GeordieP commented 6 years ago

Something about using a reserved word just doesn't sit right with me, even if it doesn't cause any issues now; can we say for sure that rest.class (for example) won't be significant to the language in x years?

gaearon commented 6 years ago

@GeordieP If it works today it can't break tomorrow. That's the core principle of how JavaScript is being evolved, and the reason for many its idiosyncrasies.

GeordieP commented 6 years ago

@gaearon Fair enough, then. If it's a big enough win, I say go for it.

gaearon commented 6 years ago

@sompylasar I usually search for className= or className:, seems like both of these would work with class too.

cozuya commented 6 years ago

Please get rid of className, and for god's sake, htmlFor. I am not a DOM developer, usually there is something very very wrong if I have to access native DOM methods. The biggest challenge I have onboarding people to React is the abstraction JSX makes over the DOM and its weird replacement HTML attributes. Everything is being transpiled, no reason to worry about reserved words at this point. IMO.

sandgraham commented 6 years ago

Not sure this is adding anything to the existing discussion, but it seems like there should be a better reason to change className.

Is saving beginner React learners from a slightly unintuitive name worthy of everyone having to update their projects & behavior?

As someone who uses de-structuring liberally, having to remember this new exception to the rule is probably a larger mental hiccup than the rare occasion that I write class instead of className.

Also, wouldn't beginners still be confused by the vast amount of material (as blogs/repos/etc) that uses className currently?

Finally, as @sompylasar said, this hurts search-ability within my codebase.

Maybe this is a tabs vs spaces type argument, but I don't totally understand why this change is necessary. It seems like a large cost for little gain unless this is part of a larger shift in how you want to model the API over time. That said, I'll for sure be using whatever ya'll decide πŸ˜….

Daniel15 commented 6 years ago

A bit offtop but it's kinda sad that no one (as far as I know of) had the idea to make a html/css/svg -> jsx transfomer in order to ease migrations to React with so many trivial changes to map HTML attrs to React props.

@jxub - I built a HTML to JSX converter as part of a hackathon way back in 2014: https://magic.reactjs.net/htmltojsx.htm. I'm not sure if it handles SVG well, though. The hackathon project was to make a script that would "ajaxify" a plain HTML site by using React (https://github.com/reactjs/react-magic) and part of that required me to build a way to create a React component from a chunk of HTML, so I released the HTML to JSX part as a separate standalone page.

We still care about supporting IE11 but it's possible that we will not attempt to smooth over some of the existing browser differences β€” which is the stance taken by many modern UI libraries.

@gaearon - What's some examples of modern UI libraries that do not smooth over browser differences? For me, that's one of the major reasons to use a library.

sompylasar commented 6 years ago

Conspiracy theory: this entire className / class news is one bright controversial thing that everybody will immediately pay attention to and argue about. It's either to attract attention to the rework project as a whole, or distract from something bigger that is happening in the shadows, or give one thing that can be later retracted while the rest will be accepted, like in the following anecdote:

The great theatrical artist Tyshler, creating sketches of scenery, in the corner drawing a small green dog. And when one of the admissions committee asked: "I like everything, but where is this dog?", The artist with a sigh of regret plastered her.

The true reasons behind this change aren't clear, but they have already skyrocketed the popularity of this new upgrade project and the community buzz around React.

koba04 commented 6 years ago

It would be nice if supporting Passive Event Listeners were within the scope of React Fire, which is an important feature on mobile.

6436

iMerica commented 6 years ago

Thanks for all your hard work on this, but please reconsider className -> class.

We were all once React newbies and className didn't prevent us from learning and loving React.

oknoorap commented 6 years ago

I remember when I'm using vue with jsx, they already had class not className, I disagree if className will be changed to class, because React is pioneer in Virtual DOM, and represent of DOM it self.

reyronald commented 6 years ago

Attach events at the React root rather than the document

@gaearon Does this mean that in a testing environment I won't have to append elements to the document to be able to dispatch real browser events and have the handlers associated to them be called? Having to do this is very counter-intuitive and I'm sure has been the source of many developers unfamiliar with React's internals get confused, waste a lot of time writing tests and incurring in event simulation and poor testing practices.

Which takes me to another note, can we do something about react-dom/test-utils ? I'm specially interested in the possible removal of Simulate given all the issues associated to it that we all know, and of course do the necessary changes in react-dom itself so that it is truly not needed anymore. Could that be in scope?

/cc @kentcdodds

jarrodconnolly commented 6 years ago

I love the direction and big picture view that React Fire is taking. So far those look like great changes to work towards.

donaldpipowitch commented 6 years ago

Love most announced changes, but I'm sceptical about the className change.

React doesn't force you to use destructuring or using this specific variable name, and writing something like (...code snippet...) isn't that much more effort.

While it isn't much effort to write, in my current experience I'd expect it to be way harder to explain to other developers (especially developers from other languages). On the other hand in all the years we used React at our company I guess only one or two devs were confused by className and just accepted this as Reacts API for setting the class names within a couple of minutes.

(In my personal opinion while I love destructing, the renaming syntax sometimes feels weird in itself for beginners, because it is different than renaming in imports which looks quite similar and can be combined with things like default values. One could just not use destructing then, but that would be a big exception to all other code we currently write at our company. Experience from others May differ of course, but that is my view on the problem πŸ™ƒ.)

behnammodi commented 6 years ago

great

mhenr18 commented 6 years ago

Also sceptical about the className change. It's one of the most minor changes in the scheme of things, but it's attracting a massive chunk of the commenting discussion here.

Is it really worth spending that much political capital on a change, when there's so much other good stuff that's being announced?

From where I stand, if you're making a decision where part of the justification is "and writing something like... ...isn't that much more effort.", that decision has got to have a massive upside, and the className -> class change just doesn't in comparison to everything else that's been announced.

rodrigooler commented 6 years ago

this will be a major advance on πŸ”₯ React Fire

gaurav- commented 6 years ago

About class v/s className, I think we should remind ourselves that JSX β‰  React.

Since JSX is a DSL that's designed to look like HTML, it's best to keep it as close to HTML as possible. Granted it's called className in the DOM API, but most are using JSX probably because they don't want to deal with DOM API directly.

If it makes more sense for React's API to closely match DOM API, then I hope it's ok/possible to do the mapping in the transpilation: <img src="avatar.png" class="profile" /> β†’ React.createElement("img", { src: "avatar.png", className: "profile" }).

It would be very valuable to make JSX syntax a clean superset of HTML.

dmitriid commented 6 years ago

To add to what @mhenr18 has said.

Current state of things:

Proposed state of things:

Perceived benefits:

If React was open sourced today, it seems like the pros of allowing class (closer conceptually to what most people expect, less typing for the most commonly used prop) outweigh the downsides (slightly more typing to intercept it β€” in which cases you'll probably just want the spread operator anyway).

Actual downsides:

If I were a product manager, my immediate reaction to the change would be: wat?

ManasJayanth commented 6 years ago

@gaearon You might have considered this already, please tag PRs with "React Fire" or a similar keyword.

Issues usually are tagged correctly, PRs sometimes don't have them. This helps potential contributors. This is coming from my experience when I was trying to read through the git history looking for React Fiber and React Reconciler related commits during the whole Fiber development. It helps those of us who are who are trying to figure out whats happening and see if we can contribute in some ways.

foxylion commented 6 years ago

I also think renaming className to class will cause such a big migration effort and problems for new devs. The className attribute is so visible and heavily used that it will literally break all libraries relying on react. And this is not enough, most tutorials will be broken. A new device copy & pasting from an article will be wondering "why is that not working, it says className is not a valid prop". So the senior has to help and we have not gained anything, because we still have to explain why it does not work like you would expect. And for real, explaining that you have to use className to define classes on the component takes under a minute and is easily understandable. Explaining why they changed from className to class to every developer takes much longer and results in more frustration.

All the efforts required for a single word. It will not change anything in the way react behaves. It will not boost the development of react-dom. It will not increase productivity of devs working longer than a week with react. It will just break everything.

Please think about it, is it really worth it?

gigobyte commented 6 years ago

I have been using babel-plugin-react-html-attrs for years and it has been serving me well, I don't think renaming className to class is a good idea. It's better achieved by a plugin like the one I mentioned.

rdev commented 6 years ago

Wasn’t there a Babel plugin to handle the whole β€œclass v classNameβ€œ / β€œfor v htmlForβ€œ situation?

gaurav- commented 6 years ago

I hope it's possible to support html attributes as-is while maintaining backward compatibility with the naming decisions already made.

The fact that there are babel plugins already to do the conversion, is perhaps evidence that it should be possible to support it in the core JSX transpiler itself. But making it an official spec would make things so much easier and reliable for everyone.

I'm not aware of React internals, so can't say much about the real feasibility. Only expressing how I think it "should be" in terms of user-friendliness.

kLabz commented 6 years ago

Please reconsider className vs class. As it has been said above, the gain is almost inexistant but there are real downsides.

One being that for us using Haxe as a language to write react applications, this would not only be a breaking change but will simply prevent us from writing any react application.

class is a reserved keyword in most programming languages, and we could simply not manipulate this prop anymore, making react application near impossible (good luck creating a real one without manipulating classes). Same goes for htmlFor vs for, sadly (this one is really ugly but I'm grateful it exists).

sompylasar commented 6 years ago

Oh by the way, searchability... Imagine you google for "React class", you'll get mixed signals: React class components, React class attribute. You google for "React className", you'll get outdated documentation (people mentioned above the huge amount of upgrade work geterated by this change besides code upgrades).

Is the goal of this project to generate more work for the community and more noise and mixed signals for the Internet? I hope not.

Yes, the Web and JavaScript ecosystem struggles to maintain back-compat with stupid mistakes of the past, but this strive for back-compat is what allowed it to grow up to such scale without major fragmentation.

I understand that there's no progress without change, and myself adopted the early FB's motto of breaking things to move fast (also having a plan how to re-assemble them back in advance).

If you're being so persistent that this change is really needed, just tell the true reason for the change. It can't be the "hard to learn" thing, sounds too shallow for the mighty React Core team. You definitely should have something in mind.