Hacker News new | past | comments | ask | show | jobs | submit login
React v0.12 (facebook.github.io)
226 points by sophiebits on Oct 28, 2014 | hide | past | favorite | 77 comments



I don't know if I'm reading the changes wrong, but I'm not liking how I have to do an extra step if I don't use jsx. I want to use coffescript and not have to do extra stuff.

I definitely feel this forced vibe around making everyone use jsx, but have yet to hear any compelling reasons why it's better.


Hi, this was a tough call for us to make. We wanted to everything we could to avoid extra bloat for everyone. In the end, most people tend to use some kind of extra helper, even if it's not JSX. E.g. a custom library or another third party language.

One reason for this change is to make it possible to use object literals or record syntax where that is more appropriate than function calls. We don't currently recommend it because there's no validation in that case, so you probably want static analysis to catch errors. I would encourage you to play with the idea of using object literals instead of function calls though.

One compelling reason for this change is that in 0.13 you will be able to build components using plain CoffeeScript classes instead of relying on React.createClass. So, in the end, you will be getting some of that bloat/overhead back.

We're definitely not making React depend on JSX. We will continue to support non-JSX and fully support compile-to-JS languages. Unfortunately, that sometimes means a trade-off. In this case trading React.createClass for React.createFactory. Some would've preferred it be the opposite tradeoff but React.createFactory gives us more benefits than the opposite.


More information in breaking changes would definitely be appreciated.

I can't decode what "Composite Component functions can no longer be called directly" means exactly in terms of code that will no longer work.

I definitely use React without JSX in plain JavaScript and I really love it. I'm kind of dreading what this little snippet means when I try to update to 0.13.


> One reason for this change is to make it possible to use object literals or record syntax where that is more appropriate than function calls

I think this will be the most revolutionary aspect in the next months, both for development and tests. I wrote an article explaining why I have this opinion:

https://gcanti.github.io/2014/10/29/understanding-react-and-...


Thanks for the response.

Could you give me a quick example of calling a component with object literals instead of functions? I'm not understanding how that will play out in the final code.

Also, isn't it just adding React.createFactory, not replacing React.createClass?


In CoffeeScript it might look something like this:

element = type: 'div' props: className: 'container', children: [ type: 'span', props: className: 'foo' type: CustomClass, props: className: 'bar' ]

(This doesn't fully work in 0.12 because we also have some extra properties on there but that's the direction we're going.)

0.12 is just adding React.createFactory. 0.13 will optionally replace React.createClass.

We do this so that there's a seamless upgrade path. We have to remove the warnings to fix the classes.


I guessed that indentation:

    element =
      type: 'div'
      props: className: 'container'
      children: [
          type: 'span'
          props: className: 'foo'
      ,
          type: CustomClass
          props: className: 'bar' 
      ]


Thanks for the answers.

I will say that I do really like the syntax of coffeescript as is though,

  div className: 'container',
    span className: 'foo'
    CustomClass classname: 'bar'
It reminds me a lot of slim and reads nicely.


Big-R (the react framework I've been working on) eases this transition a bit. You can see[1] that components aren't accessed directly (unless of course you want to)

It still doesn't solve the stuff JSX has for splats though ...

[1]: https://gist.github.com/mikew/e737273e42ed704c6c54#file-zz-r...


Where did you see the increased difficulty if you weren't using JSX?


I haven't used React, but maybe he's referring to this: "Composite Component functions can no longer be called directly - they must be wrapped with React.createFactory first. This is handled for you when using JSX."


As the others have stated, react requires me to add this line: var MyComponent = React.createFactory(require('MyComponent'));

It's not a huge deal, but I keep getting this sense that jsx is strongly tied to react and this reaffirms that they are going to keep it that way. I do trust the react team still, but it makes me weary of future releases.


(I'll re-link to sebmarkbage's answer here in case people see this post and get confused: https://news.ycombinator.com/item?id=8523876)

In short, this is somewhat of a transition step for the (imo) even better way of specifying your render with pure vanilla js collections. This goes in the opposite direction of what you're worried about. You can view `createElement/Factory` as the stepping stone, with the _additional_ benefit of allowing you to use es6 classes very soon. Smaller API surface and + using more js features rather than library-specific ones; what's not to like? =)

As for your worries about JSX: yes, it does come from React since the beginning. But we've taken an extra step of making it clear that this doesn't have to be React-specific: http://facebook.github.io/jsx/. You can plug this in CoffeeScript. If not, see my previous point.


His concerns about JSX are the opposite of those you site, I believe; him (and I) want to use React without JSX whatsoever.

As long as we can always do something like

    div className: 'foo', 
      span className: 'bar'
      Custom className: 'baz'
I think we'll be reasonably happy. But nobody likes feeling like a second-class citizen =)


Why not just use jsx though? It's almost always easier.


How so?


It's similar to standard HTML and less clunky than the equivalent JS expressions


You don't need to do a separate step to use JSX. JSX is a still a superset of JS and you can still opt to not use it with no additional steps.


He's referring to the createFactory stuff. The new JSX transformer automatically generates that boilerplate for you, but if you don't use JSX you'll need to add it everywhere yourself before you upgrade.


"...but I'm not liking how I have to do an extra step if I don't use jsx."

http://facebook.github.io/react/blog/2014/10/14/introducing-...


"Composite Component functions can no longer be called directly - they must be wrapped with React.createFactory first. This is handled for you when using JSX."


I'm disappointed that JSX is now so coupled to React. I was looking forward to JSX being used by many different JavaScript frameworks[1], but this change reveals the devs are not interested in moving that direction.

[1] Example: https://github.com/mrsweaters/mithril-rails


We do actually want JSX to be flexible and usable for not just React, which is why we're trying to write a formal specification of the syntax with multiple parser implementations:

http://facebook.github.io/jsx/

We intentionally don't specify semantics to give different transpilers the flexibility to compile the JSX into whatever's appropriate for the library you're using.


A specification is great, and I'm happy to see that. However, even though it's true that transpilers can compile JSX with arbitrary semantics, it still requires writing your own transpiler.

JSX is a great syntax, and these changes mean nothing if you're a transpiler writer. What I was hoping for was the JSX transpiler that React uses would become flexible enough for any library to use, without the need to modify/rewrite the transpiler itself.

Yes it's possible for someone else to write something like this, but writing a compiler is no small feat =/


    JSX is a great syntax
It's really not. It's just mixing syntaxes to solve the problem that mixed syntaxes causes. Higher order functions (i.e. createFactory) is a much better solution.


Yea, note that mithril is on that list. The syntax was where people unified. There wasn't agreement on semantics and this is moving closer to that.

It's possible that this will eventually unify again. E.g. around a replacement for an object literal. E.g. a standard record type.


React looks interesting JSX does not. I was considering using React for my next project , but I really do not want JSX or Coffescript or any of this other crap. Dojo suffered terribly by having a split brain, I think you guys a following a well worn path.

I don't care if JSX is this or that, I simply have no interest in using or learning it because its not significant enough nor applicable outside of your framework and enforces anyone else who I work with to also adopt it.

This isn't just my opinion, having discussed using React this was the general consensus in a team of very different people, I stated that its fine because you don'e need to use JSX ... but at the moment it looks like you are focusing on moving developers in the direction we don't want to go.


Use react-hyperscript [0] instead.

I'm not sure if it's yet been updated to support createFactory, but even if it doesn't you could create a simple higher order function the partially applies the static unchanging DOM parts, returning a function that takes the same data type as the function returned by createFactory.

IMHO, with createFactory, there is no longer a good justification for JSX. JSX basically solves a problem that JSX created. The reason people like JSX is that it takes the unchanging DOM structure (basically the virtual DOM equivalent of HTML templating) and puts it in HTML like templates do. This gives it a sufficiently different syntax, that it's easy to visually discern the changing parts from the unchanging parts, especially with syntax highlighting support. However, with createFactory, you have a way to wrap up all the unchanging structure, such that you don't have to constantly have to mentally parse the unchanging structure from the virtual DOM that render() is actually going to update. This means you still have to deal with React.DOM, but if you use react-hyperscript, the syntax is sufficiently simplified that it's comparable to HTML.

The complexity of JSX simply isn't worth it. It breaks too many tools.

[0] https://github.com/mlmorg/react-hyperscript


What options are there for syncing flux stores on the server and client?

I ask this because the increasing move towards microservices seems to suggest that "joins" are going to start taking place on the client via waitFor.

For example, if I get model A and it depends on Models B, C and D. I don't want to have to wait for the client to fetch model A before it knows it needs to fetch models, B, C and D. Ideally, as model A passes through the server side store layer, it already starts fetching models B, C and D so it has those ready to serve to client, (or better yet it anticipates that the client is going to want B, C and D and eagerly sends that data to the client).


I think a real-world example might help to describe what you mean. Perhaps you could normalise the data in a way (on the server-side) that would remove the need for this setup?


That sounds like a problem of pushing too much processing to the client side.


A downvote for pointing that out.

Can someone explain why I would want to do joins on the client side, when there is mature, well tested, well understood technology for doing joins on the server side? All the data is going to be on the server, so no danger of loosing a connection.


I have a huge problem with this change explained here: https://gist.github.com/deadlyicon/da8c020662ea8e6002dc



The object literal syntax also sucks :(

https://gist.github.com/deadlyicon/79c09610cac5a67f4a5d


Agreed.

* JSX more tightly coupled,

* less straightforward JSX->JS mapping - I used to be so excited to tell people how JSX simply maps to function calls in JS... well, now it generates boilerplate instead.

* worse non-JSX syntax

I don't buy the ES6/CS/TS argument - wrapping classes with createFactory before exporting seems fine to me, and I use typescript. Also, from what I can see the object literal syntax is always worse.

So its basically all about Jest. The only reason I see is that a mocking tool can't handle factories. Makes me a bit sad. Seems like a good example of "test induced design damage" to me. How about adding plugins to that mocking tool instead?


If you wrap the class in createFactory() then you break instanceof; how is this fine?


True. But I can't come up with an example where I'd use instanceof on react components, can you give me one?


Just wondering .. maybe it's used internally by the library?


See my link on sebmarkbage's reply. It's not just for Jest.


Okay, except for JSX I agree that the change towards native classes is for the better.

But the change in JSX seems to be just for Jest. JSX could still compile to function calls and stay completely decoupled from React. A new function `createFactory` would be introduced that takes a class argument and produces a factory, making ES6, CS and TS users pleased. No backward-compatibility breakage would be introduced.

edit: removed a non-constructive paragraph. Will play around with the new version more before commenting further. Hopefully I'll understand why JSX is a lot more complicated than it used to be :/



A sincere and big thank you for building and evolving this awesome tool that simplified UI madness in browsers. :-)


As a person who is using react, this is a welcome change! I'm glad they're taking time to get rid of the kludgy code that wasn't quite consistent.


Hey can you explain how they improved consistency because I just don't understand how the new changes help. I may just not understand what they did at a fundamental level.


IMHO it's more consistent because the things that react has been modifying have been Elements all along (DOM Elements).

React called them components, and it's always felt like a kludge to create some thing that WAS a DOM element (boiling down to React.DOM), and then set it's "tagname" as an after-thought.

Things like prop are tied directly to the DOM Element, further suggesting that the "thing" the component was, was actually a DOM Element.

I guess it's really subjective, but I think it'll be clearer to explain to people now:

"React manages creation and rendering of dynamic/intelligent (DOM) Elements"

(bonus points for no overlap with the Web Components terminology)

But then again a lot of this is just my opinion, consistency


Always really happy to see a ton of breaking changes in a pre-1.0 release, and very pleased that they're all moving towards simplifying the public API.


Ouch. I've been building dynamic components using transferPropsTo(), which is now deprecated. It's very flexible and working well, so I'm a bit bummed to see it go.

  render: function() {
    // after building up some object, propsObj that is determined by state

    return this.transferPropsTo(
      Component(propsObj)
    );
  }


No problem, just do this instead:

  render: function() {
    // Assign propsObj here

    return <Component {...propsObj}/>;
  }


I don't get the React.isValidComponent -> React.isValidElement change. Wasn't "class" the name of the abstract idea of component and "component" the name of the actually rendered component, the class materialized in a DOM?


See this post for a description of our terminology:

http://facebook.github.io/react/blog/2014/10/14/introducing-...

If I write

  var C = React.createClass(...);

  var e = <C />;
  var c = React.render(e, document.body);
then C is a class, e is an element (previously "descriptor"), and c is the actual mounted component. Components are generally accessible only through "this", refs, and the return value of React.render.


One of my favorite patterns in React is using functions to wrap a React component.

It goes something like this:

  App.Button = React.createClass({
    render: function(){
      var className = 'btn '+this.props.className
      <a href className={className}>{this.props.children}</a>
    }
  });

  App.BigButton = function(props){
    props = props || {};
    props.className = 'btn-large '+props.className
    return App.Button.apply(null, arguments)
  };
How would you do something like this?


This is actually an anti-pattern that we're explicitly trying to get rid of. The fewer components you have, the fewer optimization hooks you have. This also have subtle changes in semantics, and disables local optimizations in the consuming files.

The idea of a lightweight declaration of a component (e.g. a just function) is definitely still on the table and might be resurrected in a different form.

https://github.com/reactjs/react-future/blob/master/01%20-%2...


The suggested way of doing this is define a new component like so:

  var BigButton = React.createClass({
    render: function() {
      return (
        <Button
          {...this.props}
          className={'btn-large ' + this.props.className} />
      );
    }
  });
(Before React 0.12 introduced the JSX spread syntax, this was handled by transferPropsTo.)


So are ES6 classes for components coming in 0.13?


You can use ES6 classes today:

    class Button {
      render() {
        return <button>{this.props.label}</button>;
      }
    }

    Button = React.createClass(Button.prototype);
Of course, it would have been nice to be able to skip that last line, and extend/mix in some React base class instead.


Maybe. We're still working on the details about what that will look like. Chances are we'll have some basic support if you're doing a limited set of things. Stay tuned.


I've been looking into React.js recently and I have a general question. Is it possible to use React.js with zurb foundation cleanly? It appears that it will not work well because Foundation expects to modify the state of the DOM for Foundation elements. Are there any workarounds?


After looking into this I've come to the conclusion that rewriting the JavaScript to handle events through React's system is the best way to include Foundation's JS components. (This is something I'm planning to do with Foundation-for-Apps since I won't be using Angular).

That said, the styles are still usable without modification and you could tell React to not handle pieces of the DOM in some cases for the existing JS.


The license change paragraph mentions patents. Anyone knows which Facebook patents are used in React?


How are bindings in React not two-way? Update an input field and it updates the underlying JS object. Update the object and it updates the input field. I thought that was the definition of two-way, regardless of what happens behind the scenes.


It doesn't update the underlying object for you by default.

If you use an uncontrolled component (by giving it a defaultValue/defaultChecked prop) you have to pick up the new value using an event or directly via the DOM. If you do it this way, you can't update the displayed value by changing the props passed to it.

If you use a controlled component (by giving it a value/checked prop), its displayed value won't update unless you pick up the new value from an event and set it in whichever JS object you have holding its state for the next render. There's a helper for doing that, or it's easy enough to roll your own event handler which takes care of all your fields.

http://facebook.github.io/react/docs/forms.html


Can someone explain what the "spread operator" is and how to use it?


Spread is like python's *args.

Instead of this:

  var mapArgs = function() {
    var args = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
    var mapper = Array.prototype.slice.call(arguments, arguments.length - 1);
    return args.map(mapper);
  };
You can do this:

  var mapArgs = function(...args, mapper) {
    return args.map(mapper);
  };
And you can also use it to apply. Instead of:

  var max = Math.max.apply(null, [1, 2, 3, 4]);
You can do:

  var max = Math.max(...[1, 2, 3, 4]);


heydenberk explained it well, but just to add some clarity on why you'd want to use prototype.apply for array as an argument -

http://stackoverflow.com/questions/2856059/passing-an-array-...

http://stackoverflow.com/questions/1316371/converting-a-java...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

I'm still learning more about JS and so I'm no expert, but it seems to be similar in concept to use the ... in other languages. I think Groovy has something similar and Java has the varargs. They have obvious differences, but conceptually I think of it as passing in a variable number of args.



Wow, the example in that gist:

  var component = <Component {...props} foo={'override'} />;
Wha?? For me, there's a point in a language where the benefits of syntactic sugar are outweighed by readability concerns.


Are the v0.11 docs available anywhere other than the Github markdown files?


off topic a bit, but why do the CDN urls 301 redirect?


Mostly what @BinaryBullet said. fb.me is a urlshortener and then it hits real CDNed files. I (as maintainer of React) suggest not actually using fb.me urls in production. Use cdnjs or jsdelivr. Or host it yourself. We've been meaning to put together a proper CDN hosting setup for JS libraries but just haven't gotten around to it.


Ok, thanks. That is what I am actually doing now (host it yourself). It might be nice to mention that in the documentation/article that those links shouldn't not be used on production. Currently it is definitely not the messaging that comes across. eg. "Minified build for production: http://fb.me/react-0.12.0.min.js"


Out of curiosity why don't you suggest using the fb.me urls in production? It would be nice to take advantage of the reach of Facebook to know that a decent percentage of users would have hit the CDN'ed react url before hitting non-fb site(s).


Do you mean the fb.me link, or did you see one of the fbcdn.net links redirect? If you mean the fb.me link, that's Facebook's URL shortening service, so those will always redirect (as far as I know).


I really don't see the point of making so much breaking changes just to simplify the public API. The thing was working, it was good. It didn't need any changes. God would have rested.

But well, the developers were there and, you know, they cannot see a repository without commits for much time, right?


Their earlier blog post gives reasons for each of the API changes they made:

https://facebook.github.io/react/blog/2014/10/14/introducing...


We made these changes to try to make React better for everyone, but if you would like to continue using React 0.11, please do.


Please, don't take this as an offense. I didn't mean to. This was an attempt of a joke, but it clearly didn't come out the way I wanted.

I love React, I love you guys for making React and I'm sorry for this comment.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: