A lot of great ideas in this release and it makes me excited for the future of React.
I've been on 0.14-rc1 and my favorite feature so far is stateless function components. So much cleaner than class-based components.
One downside is that hot reloading doesn't work with it yet (AFAIK). Hopefully that will come soon now that 0.14 is officially released. (And I believe Dan is/was on vacation.)
Andrew Clark (core contributor to Redux and creator of Flummox) just released Recompose which provides powerful capabilities for stateless components: https://github.com/acdlite/recompose.
Some of the benefits of stateless function components as outlined in Recompose's readme:
* They prevent abuse of the setState() API, favoring props instead.
* They're simpler, and therefore less error-prone.
* They encourage the smart vs. dumb component pattern.
* They encourage code that is more reusable and modular.
* They discourage giant, complicated components that do too many things.
* In the future, they will allow React to make performance optimizations by avoiding unnecessary checks and memory allocations.
>One downside is that hot reloading doesn't work with it yet (AFAIK). Hopefully that will come soon now that 0.14 is officially released. (And I believe Dan is/was on vacation.)
There's work in progress on this, and I'll try to release an update to React Transform & friends handling this next week.
Might take longer to retrofit this into React Hot Loader but if there's enough demand I can try doing this too.
The idea of giving special consideration to "stateless" UI components in this sense seems ill-conceived, because adding or removing UI-related state should not have any extra implications.
For example, if you display photos in a table, there is no state, but if you display photos with a carousel, then you have state as the current page, but these two components should otherwise have the same interface and implementation. Also in general the current selection and scroll position is state, albeit stored in the browser, so any UI component can potentially have state, even if it is only stored implicitly in the DOM objects.
What really matters is whether the component holds any state with "semantic" meaning or that needs to be persisted (like a date the user selected in a date picker) or whether all the state is "presentational" (like the month a date picker is showing).
What you should do in React is not hold any "semantic" state in components, unless it's a component that is solely designed for holding and managing such state (e.g. Relay container components, or a root App component).
EDIT: slightly reworded to be clearer and more correct, since having the same API interface regardless of statefulness is implicit in React
You embed stateless (function-based) components just like you do for normal components. There is no interface difference; the caller doesn't need to know whether the component it is using is stateless or not.
> The idea of giving special consideration to "stateless" UI components in this sense seems ill-conceived, because adding or removing UI-related state should not have any extra implications.
But… it doesn't? 0.14 just provides a simpler way to define stateless components. For a component user, there should be no difference between a "functional" stateless component and am "object" stateless component which defines a whole class with only a render method.
> The idea of having "stateless" UI components in this sense seems ill-conceived, because whether a UI component has state should not be a concern of the user of the component.
I might not understand your point, but the user of the component shouldn't have any need to know whether it's stateful. A stateless `Photo` function component should have the same interface as a `Photo` class component: `<Photo ... />`.
Thanks for the link! Should clarify that Recompose works equally well with stateful components created with either createClass or React.Component. It just happens to be especially useful for stateless functional components :)
What exactly is different? I've been using "stateless function components" with react 0.12 and 0.13. Just write a function that returns a ReactElement, eg:
function renderFoo(props) {
return <span>{props.foo}</span>;
}
Then use it elsewhere in your code like a normal function:
function bar(props) {
return <div>{props.foos.map(renderFoo)}</div>;
}
Also in the future this pattern will be faster thanks to React not having to maintain an internal instance for such components.
(How's that different from just a function? It shows up as separate thing in React DevTools, it can have default props or, in the future, shouldComponentUpdate (or built-in memoization strategy?), you can potentially later change it to be stateful without rewriting consuming code, etc)
I also like stateless function components. If you are using Redux, all the state management can be done at Redux side and you can make all React components stateless. And they become even easier to write after this release.
The Elm and Reagent (Clojurescript) communities build apps this way. It's theoretically possible to do everything in render in practice you wind up wanting to do things in other lifecycle events (e.g. display a google map) in most apps. There isn't any component local state but the components aren't pure render functions either.
In general, interacting with anything that does more interactive rendering (three.js, google maps, ads, etc) requires access to lifecycle events beyond a simple render method...
In the past I've had to keep a handle on the DOM nodes for ad slots that may hide/reshow when a window was re-sized, so the same ad was kept.
However, this should be the exception to the rule, and I still love the React way over components (Polymer) or angular directives.
That should be possible! Of course, stateless components don't have state, so you would need to something like Recompose if you need that. And of course, not all React-related projects explicitly support stateless components at the moment (e.g. hot reloading).
I generally try to do everything in render(). It almost always works out better. Sometimes I end up needing a lifecycle event. Timers (e.g., for manual animations) end up being hard to model without mount/unmount.
Agreed.. using mount/unmount is the exception to the rule.. I can imagine anything using charting libraries, or any third party rendering library would need to do this for performant controls... but it is definitely the exception to the rule.
> Like always, we have a few breaking changes in this release. We know changes can be painful (the Facebook codebase has over 15,000 React components), so we always try to make changes gradually in order to minimize the pain.
Since React is a semver project, from the website:
> How do I know when to release 1.0.0?
> If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you're worrying a lot about backwards compatibility, you should probably already be 1.0.0.
I can't help but feel that maybe Semver made a mistake by including 0.x at all.
It's rare that you don't see a bit of software churn through a few breaking versions rapidly while in the early stages of development, many of which happen well after attracting significant public interest and dependence. Semver provides for this already with the major version and for pre-releases with the `-alpha`, `-beta`, `-rc` suffixes, so 0.x in this case seems to provide developers with an out-clause to consider major revisions non-major and put off committing to 1.0 for far too long.
This also seems to be at least partially fuelled by a historical aversion to hitting double-digit major versions, although we owe Chrome a debt of gratitude for demonstrating to us that there's little to fear by doing so. Hopefully this approach continues to catch on.
Would React's users (and the users of many other extremely popular libraries/tools doing the same 0.x dance) have been better served by declaring a 1.0 version much, much earlier in the development process? I think so.
>To teams who are using it in production, did you talk about this? What are arguments for using it despite it not being 1.0?
That it's stabler than most 1.0+ libraries is a good argument.
Facebook uses React at massive scale, so they're very careful with changes, go out of their way to keep deprecated behavior for at least a version (and a version takes a few months), provide codemods for changes that can be automated, provide useful warnings, run React master in FB production, and catch many issues in internal FB-specific tests before they even reach the React master. This is as stable as you can get without stagnating the platform.
PS Yeah it's a bit frustrating React doesn't bump majors and bumps 0.x minors instead and yes semver says “production better be 1.x” but realistically I choose real stability over “fully adhering to semver production-is-above-zero doctrine” any day, and stability is what React releases deliver. As long as NPM understands what breaking changes are (and caret gives the intended meaning for 0.x), I don't really care which number as bumped, as long as the migration is relatively painless, and the platform moves into the right direction.
> That it's stabler than most 1.0+ libraries is a good argument.
What exactly do you mean by stability here? A 1.0 library (according to semver) is not allowed to break compatibility unless they bump to 2.0.
Pre 1.0 version 0.14 is equivalent to version 14 if it had been 1.0. That's 14 breaking change in about 2 years. Or 7 a year. That's a lot. That's not stable.
>Pre 1.0 version 0.14 is equivalent to version 14 if it had been 1.0. That's 14 breaking change in about 2 years. Or 7 a year. That's a lot. That's not stable.
I mean “stable” by “takes 2 hours to update the code once in three months”. Are you building websites or rockets?
I'm guessing here, but I'd fathom that "stabler" means that it has less severe bugs than most libraries, but is true given the number of eyes on it and its popular following.
We're migrating from Backbone to React, and it's been lovely. Our main argument is essentially what the grandparent said: based on the policies React has been following, it basically behaves like a 1.0 release. There's clear deprecation warnings and announcements, and those are caught by our test suite. The only backwards-incompatible changes that have happened since we started using it earlier this year have been mostly painless Ctrl+F fixes, and even the bigger ones (ReactDOM, etc.) have not been too much of a problem. And from a logical perspective, if it's stable enough for Facebook (Alexa #2) to use for production, it's stable enough for a smallish HR software company.
Tangenital, but I think backbone still has a place post react.
React fills the void between web components and app flow, but it's not the whole story - it still confabulates data structure and function - whereas backbone handles views at a more abstract level.
An html input that does something cool is basically what web components are intended for. A module composed of several of these micro components is where react is beautifully elegant, whilst something like backbone deals entirely in spreading of concerns presented via object literals with benefits.
Backbone may not necessarily be the solution to the problem but it operates in a similar space to flux, such as it is, rather than react.
We've had good luck embedding React components inside of Backbone views. The downside is that you can't really go the opposite way (embed a small pre-existing Backbone view inside of a React component), at least without risking some weird behaviors.
Why do you care about an imaginary number? FB (and many other large companies) heavily use this in production, and have to migrate their own apps. FB even goes farther and uses the master branch (well, synced every week or so). That's a far heavier endorsement than whatever side of a decimal a number falls on.
> Not everyone has Facebook's budget or resources to upgrade every 2 months.
Even if you're FB, dedicating the engineering time to upgrading/testing/deploying 15k+ components by making a breaking change would be madness.
Anecdotally, when the React team breaks something (rare) a lot of people internally start yelling, and it never makes it into the releases. FB makes for one-hell of an integration test environment.
I care because it's a convention. Without knowing too much about Angular 2, I know that it's got major breaking changes compared to Angular 1. Likewise, I know that a 1.15.2 should upgrade from a 1.15.1 fairly trivially, whereas a 1.16.0 might take a little more consideration.
With all that said, the responses to my question are very reasonable, such as "people I know and respect have used it and stated sane upgrades historically." In the absence of this piece of tech in my own social circle, SemVer is a convention that Facebook will have to live up to. 6 months to a year after Facebook switches to it, I can research how reasonable they are with introducing breaking changes and supporting old, stable versions. I believe that more people will be vocal about a major breaking change post 1.0 than pre-1.0.
>To teams who are using it in production, did you talk about this? What are arguments for using it despite it not being 1.0?
The main argument is that "1.0" is an arbitrary number (semvers or not).
There are hellish unstable and buggy projects on version 4.x and stable, production-proven projects on 0.x.
Not to mention projects that when going from 2.x to 3.x or so, decide to just rewrite everything with new APIs and incompatible changes (of course semver allows this, but as it's also often accompanied by core devs abandoning the 2.x version, you're left with either an EOLed codebase or a breaking-changes rewrite).
That which we call a rose by any other name would smell as sweet.
Perhaps it would, if that other name had been chosen from the start.
However, in this case, many projects will have existing code using the earlier conventions.
Moreover, there is a substantial volume of documentation and tutorial blog posts and conference videos and example code repos using those older conventions, all of which has just been invalidated. This isn't just a loss, it is all now actively harmful to new developers adopting React or those trying to update to a newer version, because it's actually misleading.
If a library you're thinking of using in production is as willing to break API compatibility as React is, even if the changes are mostly announced a little way in advance, you should think long and hard about the overheads and instability you're going to incur with a dependency on that library before you adopt it. Move fast and break stuff might work if you're Facebook and thus have both final control over the library in question and effectively unlimited resources to maintain your code base, but it doesn't work very well for the 99.999% of web development projects that don't have those resources available.
To be fair, the React project itself seems to be quite transparent about its development methods. It's not as if they're advertising the library as stable -- it's still clearly shown as a 0.x version, for example. However, a lot of people are jumping on the bandwagon anyway and just hoping for the best, and that's probably not a good idea.
From an API point of view, all of that is what's in a name.
Only after a 1.0 release. 0.x implies that breaking changes are always possible
My experience has been that the React team provides plenty of advance warning with deprecation notices, similar to the experience of others I've never really been caught out by anything
The worst case I've dealt with is bringing an app from .12 to .13 after not touching the code for five or six months. It only took me a few hours to bring everything up to date.
> Only after a 1.0 release. 0.x implies that breaking changes are always possible
Yes, which is why so many projects never reach 1.0. There are basically 2 types:
1. Those who don't want to have to care about compatibility at all.
2. Those who care about compatibility a little bit but don't want a large version number.
React seems to fall into #2 here. They want a small version number and the perception of stability. But in reality there have been 14 breaking changes, this is version 14 software.
It's easier to convince someone to upgrade from 0.13 to 0.14 than it is 1.0 to 2.0 even though breaking changes are just as likely in the former. But the latter has a graver perception.
>2. Those who care about compatibility a little bit but don't want a large version number.
>React seems to fall into #2 here.
Seriously, a library that goes out of its way to provide useful deprecation warnings and always keeping deprecated behavior for a version, with versions coming out once in three months, and released with codemods automating the transition for you, cares a little about compatibility?
React team will eventually jump to bumping major, and it's a good question to ask, but it's a good question to ask the team instead of guessing what and why they do.
Seriously, a library that goes out of its way to provide useful deprecation warnings and always keeping deprecated behavior for a version, with versions coming out once in three months, and released with codemods automating the transition for you, cares a little about compatibility?
Yes, any library that breaks code written according to documented good practices less than six months earlier only cares a little about compatibility. Everything else you mentioned may be true, but it's also mostly irrelevant.
This isn't necessarily a criticism of the React team. As I mentioned in another post, it's not as if they're advertising more compatibility than this and then not living up to what they claimed. The problem is some people having unrealistic expectations and reading more into the high profile of React than they should.
But mere months between fundamental breaking changes in published interfaces isn't a good level of stability and longevity for most production projects, and for any of those projects that don't have realistic plans and resources available for maintaining the integration regularly, React isn't ready yet.
Most breaking changes are including warnings 2 versions ahead of time... In TFA they outlined, iirc, 2 changes that would have less time than this. This isn't a magical, final interface we're dealing with... it's iterative changes over time.
TBH, I don't like getting stuck at one point.. in practice those using React have been embracing the one-way flow that flux-like frameworks bring... This has been distilled down to Redux (imo, the best workflow option for React), which has signalled some distillation in terms of the interfaces React exposes. This is combined with different rendering paths coming to light, and I think it's pretty great.
I'm currently working in an environment that is transitioning from the old-way, to a more current way of doing things. I've been working with node since pretty early on (0.4) and was following it before that. The more I've embraced this continuously updating workflow, the less friction I've experienced as a whole. That doesn't mean no pain, just less of it overall.
The React/Facebook guys have been very good members in this larger community, and I applaud them for their efforts... Dropping their own render in favor of Babel, and reducing some of their mutation enablers only show them to be working with feedback from the community. It may be at a pace that's harder to keep up with, but that doesn't mean that they shouldn't be doing it.
I think you're misunderstanding React's API surface.
It's about 20 core methods, not a giant lib like jQuery.
From my experience, a medium sized project is adjusted to the changes in about two hours. Once every three months.
It is a big deal any time someone's code works, and then they update a dependency, and then their code doesn't work any more.
Even if the actual code changes required to update the integration are minimal, someone still needs to divert to make those changes and then test everything, which is disruptive at best. Before they can do that, they need to identify what changes are required and perhaps learn how to use any automated updating tools that are available, both of which also take time. If one person on the team wants to upgrade to access some new feature or just get a bug fix, everyone else on the team has to come along, so for example they might start seeing warnings that they'll need to investigate. As I mentioned in another post, there is a nasty hidden cost to breaking the interface of fast-moving but lightly documented libraries, because it will tend to invalidate all the tutorials and example repos and demo videos and so on offered by other contributors or, worse, those resources may become actively misleading.
This is a lesson the web development community will learn in time. Unfortunately today it is a very young part of the industry, obsessed with the appearance of making progress, even though actually web development is almost comically inefficient. The lack of respect for issues like standardisation, compatibility and portability is a major contributing factor in that inefficiency, as is the willingness to build on fragile dependencies in the first place.
Yes, they care. But they care more about their ability to make breaking changes without the stench of a major version bump.
You have to ask, why is it currently not 1.0? The roadmap you linked doesn't mention it. There's a reason. So what is it?
By the way, I know you're a huge React cheerleader and that's fine, and you think I'm being critical of React here and you need to defend this. But I'm not, this is a problem throughout the JavaScript community and really the fault lies there, not with any one particular project which is doing something a lot of others are also doing.
> Only after a 1.0 release. 0.x implies that breaking changes are always possible
Oh, I didn't know that, it's unfortunate. IMO, just bump major version every time compat breaks. Otherwise projects end up mincing around forever trying to decide when the shiny 1.0 ribbon can be affixed.
> IMO, just bump major version every time compat breaks.
Some projects do this but most do not. The reason is that if you're using a project that's on version 3 and 6 months from now it's on version 12 that's going to make you think twice about using it. No one wants to go through upgrade pains constantly.
The "hack" is to never go 1.0 to hide how often you are really breaking APIs.
In reality breaking APIs should be a big freaking deal. You shouldn't do it often. You shouldn't do it just because you realized some other API might be slightly nicer. Once the shine wears off people want stability.
I think pre 1.0 should represent that breaking changes are happening more often.. a 3-month release cycle with breaking changes in pretty much every stable release doesn't bode well in that regard. However, they have been very responsive to the larger community and these additions and changes are really a good thing. Mostly they break out rendering pipelines to support multiple renderers, and they reduce opportunities for mutations, which fly in the face of a flux-like workflow.
The enthusiasm around React is infectious and I'm thinking about integrating it into one of my projects but I can't quite tell what exactly it's supposed to be used for. Is it only for SPAs or is it reasonable to consider react when you just want to add some interactions and dynamism to a page that was rendered server side?
React seems kind of like an all-or-nothing approach. It seems like overkill if you just want to provide a little more structure to jQuery spaghetti code.
Can React be a competitor to, say, Knockout? React seems more in the realm of angular or ember to me.
> is it reasonable to consider react when you just want to add some interactions and dynamism to a page that was rendered server side?
This is more or less what I've been using it for at work. My general "rule" is that if I've got a form and any other field or set of fields depends on what's happening in another field or set of fields I try wrap both parts up into a React component (with as many subcomponents as necessary). I'm using react-rails[1] and creating custom form builder modules which I include in my main form builder class. The custom form builder methods just call react_component and pass in the form object as a property to the component so I get server-side rendering of the component and the same code gets reused client-side. Obviously it can be used for much more than dynamic forms, but for what I'm currently doing this is all I need.
> React seems kind of like an all-or-nothing approach. It seems like overkill if you just want to provide a little more structure to jQuery spaghetti code.
I've found that > 90% of my front-end bugs around forms involve fields that are somehow linked. Handling that with unstructured jQuery goes from easy to a horrible mess at a nearly exponential rate as the number of interacting parts increases linearly. React makes it really easy to keep track of state and have it flow downwards as properties to subcomponents. Obviously you can go way overboard with it and I wouldn't recommend it for everything, but the ability to use it in just one troublesome spot and nowhere else if that's all you need is really cool. It's the opposite of all-or-nothing. I have a very large application that uses it in about a dozen tricky places like dynamic lists of things. The rest of the application is just plain old server-side rendered HTML.
React works great in existing websites! Last time I checked, React is about the same size as jQuery minified and gzipped.
There are many benefits to using React in an existing website: a great developer experience, performance, avoiding jQuery spaghetti, ease-of-use, etc. It might be overkill to use React for just a few components, but if you want to move to React, then you can incrementally implement components using React and then switch over fully.
> Is it only for SPAs?
In my opinion, React is like the declarative jQuery. It works just as well for SPAs as it does for traditional websites.
React is the view layer only so it's not all-or-nothing. That means it can be implemented in a traditional PHP website that's been sitting around for 10 years. And it's not overkill at all, it brings sanity to code and makes it more maintainable. You'll be able to do more with less.
React is perfect for replacing turning your cooked spaghetti into dry pasta. Entropy for the win!
Interesting you draw the Knockout comparison. I'm pretty new to React, but have done a fair amount with Knockout. I find that I use the two in very similar ways. I know knockout has a large feature set and claims to be a VMMV (whatever that means), but in practice I used it mostly to go between some dynamic JSON and DOM.
Here's an example of a web application built with React, Express and Browser Express that defines the same UI components and routes for both the server and the browser:
React is really 2 things. One is an implementation of web components which makes it a competitor to Polymer and is is useful on almost any project. Secondly, React is an implementation of the Flux architecture (one-way data binding) which is most useful for SPAs, but doesn't disrupt a static site as much as Angular does.
React is not an implementation of the Flux architecture. Flux is an architecture that works well with react.
I would argue that the primary contribution from React is not the web component aspect but the declarative, immutable-friendly approach to UI rendering
> Is it reasonable to consider react when you just want to add some interactions and dynamism to a page that was rendered server side?
Not if you want to reuse the server-generated markup. You can use it for little pieces in an otherwise static page, but it needs to own rendering of those pieces.
React is more similar to jQuery than Knockout, but it abstracts away DOM manipulation. I'd say it's better than jQuery, but not as good as web components.
I have a slightly different view of the value of React. It's not the code of the library, per se, but the development patterns. These techniques will work anywhere. If you can get yourself to use them, then React (or anything that works the same way) will be a great boon for you. If not, then you might be better off with something else. Please excuse me for this explanation, which you might already be familiar with.
Imagine your data is in a tree. Go to the very lowest nodes on the tree. You should be able to imagine that rendering these nodes is quite easy. It's just simple data. Now move up a node. Rendering this node is just rendering the data at that level and telling the next level to render. Keep doing that until you get to the very top.
The rendering at every node is now very simple. It is also very easy to write tests for: You just need to make sure that the data in the node has been rendered and that the nodes below are present.
Of course, that's just rendering a static tree. How do we deal with dynamism? In it's simplest form, you don't. Instead, any time you want to change some data in your tree, make a new tree and then render that new tree. This has the advantage that it is very simple. You tree of data is immutable, and so you never have to worry about state changing. At every change you just re-render the entire tree.
Of course, that is costly, so we can be clever and notice that we don't have to re-render the entire tree. We just have to compare the first tree with the second and re-render the highest subtrees that have changed. React does this behind the scenes.
If you are trying to do a kind of hybrid approach of using react for some parts and not for others, this is actually one of the easiest ways to do it. If you want to update your data from the server, you simple make an endpoint for the data at the top of your React tree and every time you change something you make an Ajax call from that top node to get the new data. This will cause the tree to re-render fairly efficiently.
Of course, this doesn't solve all your problems, because often you don't want to get new data from your server, you just want to update data around your tree. In this case, you need to image every node as the top of a subtree. If you want to change the data in the subtree, you simply make a request to the top of the subtree to modify the data in that subtree. This causes the entire subtree to re-render.
So the main flow is that you have a tree of data which you render. Anytime you want to modify the data, you need to make a request up the tree (never sideways and almost never downwards).
These requests can be made in many ways, but the simplest is simply by passing a callback down the tree as a piece of data. You decide which node "owns" a piece of data and then you pass a callback for modifying that data down the tree. Anyone below can potentially call that callback, which will modify the data at the top of the tree and re-render the entire tree.
There are other ways of doing it. Passing a whole whack of callbacks can be tiresome. Flux, for instance, sets up a series of singleton objects that anyone can access. You make a request of the object, it creates a new tree of data and updates the top node of the tree. (Note: Highly simplified explanation to the point of being wrong ;-) ).
Anyway, the point of this is to say that, if you want to write code this way, then you should use React or something like it. If not, you should stay away, because you will make a huge mess.
3. Generate dynamic CSS classNames for my components allowed me to get rid of stylesheets naming conventions / strategies ( BEM, etc. )
4. With the help of Flux ( yahoo's implementation ) I got rid of writing two code-bases ( front-end / back-end ). Now I'm putting everything in one place, this is awesome! ( I did it with server-side rendering, so I didn't loose anything at all )
The light-weight structure that React imposes is what lets you get rid of jquery (and much of the plugins) and Handlebars/Mustache special syntax. React removes a layer of syntax and favours using plain old JavaScript.
Since your HTML is all Javascript now, there are people that went a bit further and created libraries for modularising your CSS files, based on that components [1][2].
The basic idea is that, since you are using ReactJS and you are compiling your JSX files to normal JS files, for which you are using a tool like "browserify" or "webpack". These tools are so powerful that can capture your `require` statements and convert your "non-javascript" required modules to something that javascript can use.
In a similar way I'm using webpack & css-loader. My JSX file looks like this :
// Component.jsx
var styles = require('./Component.css'); // Component.css is a normal css file that has a .component class inside
class Component extends React.Component {
render() { return ( <div className={ styles.component }></div> ) }
}
Now your webpack / browserify tools captures those require files, parses their class names and outputs a concatenated "stylesheets.css" file that has all the class names with a hash prefix. And the final Html/Css look like this :
I think he's talking about css modules. Postcss or something like that. Webpack can generate unique names for you when you use that loader. I think it's more about webpack for #3 than react.
Would you mind explaining? As a jQuery believer, to me this looks like a selector method - getElementByID or something. I'm guessing this is against the whole idea of React.
Refs are simply references to DOM nodes that you have to specify through the ref (HTML) attribute. You can give a DOM node the ref value "foo" and then later reference it in a react component with this.refs.foo (previously this.refs.foo.getDOMNode()).
I'm glad they separated out react from the DOM. This makes it much more likely that people will export the ideas and the API of React to other languages. The API is sane for data-flow programming and the lifecycle is well-defined. The separation of properties from state can be useful in other contexts.
Great news. I just upgraded our app to 0.14-rc1 last week and particularly enjoy "refs" being direct references to the DOM nodes. Can't wait to move some of our stateless components to functional.
I'm fairly new to react, and have wondered if I was using it correctly (as intended). Almost always I have a root component that manages state, passing it to children via props. All changes to state go through that root component, either by callback (also passed as prop) or some external event.
Is this update in a sense validation of that approach?
What you've described is pretty similar to Flux or one of its variants. The main difference would be that instead of managing state inside of the root component via setState, you have an external state ("store"), which would handle the state logic and provide the appropriate values as props to the root component. So yes, it sounds like you're doing it "right".
I have a question, why is dirty-checking so great?
Whether it's Angular doing dirty-checking in the $digest cycle or React walking the virtual DOM and doing dirty-checking?
Why not just subscribe to events and update things when the model changes? That would seem to be far more efficient, and also make clear the mapping of dependencies of views on data.
Usually people say “dirty checking” when they mean “keep checking in some kind of event loop whether external entity modified some object, and if so, do something”.
In React there's no such event loop where it checks virtual DOM—React knows if it needs to compare virtual DOM trees (not arbitrarily check models for changes, for example) because all changes are explicit and happen either due to `setState()`, `forceUpdate()` or `React.render()` top-level call.
So React doesn't do dirty checking in the sense Angular does, unless by dirty checking you mean all kinds of comparisons.
Right. I guess it really depends how people define "dirty checking". What I was trying to say is that at the end of the day you do diffing on some data structure: model in Angular and virtual Dom in React.
Loop vs. one pass is an important distinction, agreed. But when we bring Angular we should be noted that Angular 2 doesn't do those checks in a loop but does comparisons in one pass only.
My biggest complaints about angular aren't really the dirty checking system that it uses (though one of them is a side effect).
My biggest complaint is the weird dependency injection system that makes it difficult to track down where something comes from. It's better in 2, but still not as straight forward as React, where your child components are simply import/require statements that you can follow through to either an installed npm module, or a relative path. I try to avoid DI in JS wherever possible, it's almost never needed, and there are almost always simpler ways.
My second largest complaint on angular, is that I find that the way it handles state (though many are moving to a more react-like approach) leads to anything outside of the "angular way" being very complicated to work around. The fact that $scope.apply() is a thing kind of sums it up pretty nicely.
For most applications (we're not all building facebook level interactions), either comparison approach is not a performance issue in practice. What I do find is the flux/react way tends to have a bit more cognitive overhead to get started with, but additional features add less additional complexity than with angular.
A bit offtopic, but DI (via IoC container) is for managing runtime dependencies, which can get complex as an app grows. DI of the IoC container flavor is never necessary (I would argue that pure DI in itself is only a good thing though for clean separation of code), but one can say many things are not necessary - its existence is for making things simpler when working with complex apps. Without an IoC container, one has to manually pass around services to those requiring them if there is some complex runtime code - it sucks greatly when working with increasingly complex code, far more than using a system with an injector to manage the runtime constructs and to act as a fetcher that retrieves the necessary instance when requested. An example of the convoluted nature of handling dependencies without such a system is when one needs to test one service that say depends on another service that is x services removed in a dependency chain. In order to properly mock for testing, one has to potentially dig x levels deep to mock all relevant methods, instead of mocking the one service of interest.
It should also be noted that imports are orthogonal to the utility of DI. ES imports does not address the runtime dependency tree, and can certainly live alongside a tool such as DI - DI is for handling runtime dependency management, importing/exporting is more for handling initialization/compile time dependency management. Confusing the two is not understanding the problems they are meant to solve.
Angular 1's DI, while extremely convenient for testing, unfortunately does rely on a hacky implementation. Angular 2's DI system is extremely robust though, using the proposed ES7 decorator standard to more properly implement DI via IoC by using the services themselves (which are imported in) to fetch the appropriate instance - Angular 2's component system also makes it extremely easy to consume the injector with one line, or even creating new injectors to silo sectors of an application into runtime modules.
Angular 2 also espouses many of the ideas that React has pioneered in frontend web development - in fact, the Angular team would be quick to admit the faults present in Angular 1, which didn't have the benefit of the current state of HTML & JavaScript in the late '00s when it was conceived (ES module standard, annotations/decorators being a potential language feature, strong browser standards support across the major 4 browser vendors, etc.). Flux-like patterns can be easily implemented in Angular 2, and may see a surge in popularity given its popularity in the React ecosystem. Uni-directional data flow is at the core of Angular 2's component system.
What does one have to pass around? You can `require`/`import` service modules directly... for that matter, with a system like redux/react, you can easily pass anything needed via properties. You can create pretty complex applications without muddying where your services come from...
I've been following Angular2, and while much better than Angular1, still think react+redux as a workflow/render solution with separate state management reducers/handlers is a better workflow... especially as feature count goes up, because complexity doesn't climb as steeply as with Angular.
Because the you have to remember all possible state of your UI in your head.
Say you subscribe to "name change" event, where you have to update your UI depends on your current UI state. Are you in list page? Are you in detail page? Is the object even currently displayed at all?
There are pros/cons to dirty checking vs. getters/setters, dirty checking seems to be more popular because it saves you a few lines of code, although I prefer getters/setters as it's much more efficient and cleaner.
Anyone find a list that says what is broken by this update? I couldn't find an easy to parse list of functions/methods/etc that have changed ||&& are broken.
If you didn't see warnings running code under 0.13, nothing should break per se, right?
And if you see warnings now, that's the stuff that will break in 0.15 but works for now.
Well i think it will take some time for libraries and components to be updated. For me currently at least react router should provide a compatible build with react 0.14
I've been on 0.14-rc1 and my favorite feature so far is stateless function components. So much cleaner than class-based components.
One downside is that hot reloading doesn't work with it yet (AFAIK). Hopefully that will come soon now that 0.14 is officially released. (And I believe Dan is/was on vacation.)
Andrew Clark (core contributor to Redux and creator of Flummox) just released Recompose which provides powerful capabilities for stateless components: https://github.com/acdlite/recompose.
Some of the benefits of stateless function components as outlined in Recompose's readme:
* They prevent abuse of the setState() API, favoring props instead.
* They're simpler, and therefore less error-prone.
* They encourage the smart vs. dumb component pattern.
* They encourage code that is more reusable and modular.
* They discourage giant, complicated components that do too many things.
* In the future, they will allow React to make performance optimizations by avoiding unnecessary checks and memory allocations.