Getting started with React

As I held a talk a while back about React and Flux from Facebook and the topic still pops up every now and then, I’ll write down my experiences on getting started with both. This post handles React, Flux will follow up later.

Both are very straight forward, but as they are different than other approaches, it’ll take some time (like minutes) to get used to them.

What is it?

Facebook build React for usage on facebook.com and also implemented instagram.com in it, too. So you can be sure to use a well tested library. I mean tested by a billion people is pretty solid!

On the React page, the role of React is summarized very nice:

Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it's easy to try it out on a small feature in an existing project.

Being only the view makes it possible to include it in every project. You can easily start and implement a new feature in React and hook that in your existing application, no matter what frameworks you’re already using. Also React doesn’t care about what Router or Model you are using.

So, what’s so special about it?

Everybody talks about it, but what is it, that makes React so much better (or at least different) than other frameworks?

  • JSX – Inline HTML
  • Clean And Explicit
  • Components Everywhere
  • One way data flow
  • Virtual DOM
  • Render Anywhere

Let’s look at them in more detail:

JSX – Inline HTML

When looking at React examples, there is one thing that catches attention for being very unusual:

React.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

HTML inside our JavaScript files? What’s that supposed to mean? Aren’t we separating concerns and have to keep the markup separated from the logic?

Almost. The reason, the markup get’s included in the JS is that both, the View in MVC and the markup have the same concern: create a view! The markup is tightly coupled to the logic we create in the View. Just look at some Handlebars template. It doesn’t make sense without the corresponding View containing the logic.

So the inline HTML is not really HTML, it is called JSX. And it is optional. There is a JSXTransformer, that translates it to plain JavaScript. The example above is transformed to:

React.render(
  React.createElement('h1', null, 'Hello, world!'),
  document.getElementById('example')
);

At first, I found the JSX very strange, too. It almost kept me from trying React out. But as it is way more convenient to write JSX than to use React rendering the plain JavaScript way, I got used to it and now I really like it! Gice it a try! For more information head over to the JSX intro.

Clean And Explicit

The React API is very straight forward and easy to learn. Basically there are just a functions for creating components (also called classes) and for rendering those. That’s it!

The minimal API has it’s roots in one of the philosophies of React: Polyfills instead of libraries. So instead of recreating a lot of stuff, missing functionality is included via polyfills. There are no Array helper or whatsoever.

Another key philosophy is being explicit. Events don’t bubble up somehow, you have to explicitly catch an event from a component, just like a callback. So it’s easy to recognize where something triggers and where it is passed along. No more events popping up without knowing where they come from, just because some component got moved!

Components Everywhere

Really everything in React is a component. There is no other thing to use. The only requirement for a compoment is to have a render function. A very basic component looks like this:

var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

React.render(
  <HelloMessage name="World!" ></HelloMessage>,
  document.getElementById('app')
);

This will render a component, displaying the passed in name. You can think of a component as a plain function. Actually, a component is a plain function, when transformed from JSX to JavaScript!

A core concept of React is, that the rendering should be predictable. The render function should never include some other logic than to render. So calling a component with the same parameters shall always return the same rendered HTML.

The data in a component can be passed in from a parent component and is available inside the component as this.props.name, just like in the example above. When it is an internal variable, it can be set via this.setState({myOtherParam: 'Hello!'}) and is then available in the component via this.state.myOtherParam.

The reason why a state has to be set via the setState function is that React needs to know, when something changed to render the new state.

Components have an pretty easy lifecycle API, too:

As you can see, there are two functions to provide the initial state (getInitialState) and the default props (getDefaultProps) for a component.

The functions names of the rest of the lifecycle events are pretty self-explanatory: componentWillMount, componentDidMount, componentWillReceiveProps, componentWillUpdate, componentDidUpdate and componentWillUnmount. So to hook some JQuery (he said JQuery!!) Plugin into your React rendered component, do so in componentDidMount und remove it in componentWillUnmount.

The shouldComponentUpdate is a bit special: it expects a boolean return value which defines whether the component should update or not. So if you know definitely by comparing your data that there is no rerender needed, return false.

The usage of simple, straight forward and encapsulated components helps a lot for the structure of an app. Each component can easily be tested and moved as it is not dependent on anything except for child components. Big win!

One way data flow

Another difference to most current frameworks is the lack of two way binding. But not because it was forgotten, no because it was left out on purpose. React prefers explicit over implicit and that’s why data will only flow in one direction.

For components this means, when a component passes data to it’s child components, it is immutable. The component can provide a callback where the parent can update it’s state. So this.props in a component is only changeable by the parent.

So data flows only down to child components, just like a waterfall. When data is changed, it only affects the childs, but never the parents.

It is a bit strange to use sometimes, for example when using an input field bound to a value in a component:

var MyComponent = React.createClass({
  getInitialState: function() {
    return {
      userInput: ''
    };
  },

  onInputChange: function() {
    this.setState({
      userInput: this.refs.myInput.getDOMNode().value
    });
  },

  render: function() {
    return (
      <div>
        <input
          ref="myInput"
          type="text"
          value={this.state.userInput}
          onChange={this.onInputChange} />
      </div>
    );
  }
});

Wow – what’s happening here? We create an input with a reference myInput. This way we can access the real DOM node of the input and acced the value of that DOM node on change. When the state is updated, React recognizes a change to this.state.userInput and rerenders the component.

Of course this kind of example looks way easier in other frameworks with two way binding, but the advantage of this approach is that it is predictable what will happen. Also hooking in for a validation of the user input is very easy. A reason for using this approach is that React uses a virtual DOM.

Also, if you really cannot live with this, there are Addons for React and one of them are Two-Way Binding Helpers.

Virtual DOM

The virtual DOM is what React uses internally for the rendering. React starts with a React.render call like in the example further above:

React.render(
  <HelloMessage name="World!" ></HelloMessage>,
  document.getElementById('app')
);

It will render the specified component and all child components, depending on the passed in data. The rendered markup will be written once to the real DOM into the element specified. But it is also kept in JavaScript. When the state of a component or the data we passed in the root component changes, React will re-render all the DOM, but the virtual one! This is good old 90’s refresh, but improved!

When it re-rendered the virtual DOM, React compares that to the virtual DOM before and figures out the most minimal actions needed to update the real DOM. So as interacting with the real DOM often is the bottleneck in web applications, the impact of this is huge.

So now the example with the input field makes way more sense! We have to subscribe to the real DOM node via the ref, as the user is interacting with that. Then we tell React to update the virtual DOM which updates the real DOM with the user input data. It’s a roundtrip, yes, but a predictable one.

Render Anywhere

So we saw that React keeps a virtual DOM with the rendered markup. Why not use that somewhere else? If you looked in the React API before, you may have noticed two functions: renderToString and renderToStaticMarkup.

renderToString will render the virtual DOM to a plain text string. Wait, does that mean…? Yes – we can use that on the server! The components look exactly the same and instead of React.render, React.renderToString is used. renderToStaticMarkup behaves the same, but won’t have data-react-id on the elements. Actually, my photography website (roka.photography) is build with React on the server side.

Some people, for example the folks over at Flipboard, use React to render to a canvas. Although the usage of a canvas rendered application is horrible for accessibility, the possibilities are endless. But that’s another topic.

Just recently on the React conf, React Native got announced. It uses the same principles and renderes native UI elements on Android and IOS.

Conclusion

React comes along very strange at first, because it is breaking with a lot of what is the current state of the art in frameworks. But many of the concepts of React are really great.

The API is very easy and it is fast because of the virtual DOM. Everything is predictable and it is possible to write real isomorphic applications where we use the exact same code on the server and the client side.

I’m looking forward to what comes next!