What is React, and what does it actually solve?

Open Source

A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

What React isn't

  • MVC framework
  • Templating library
  • 2-way data-binding

Basically just the V in MCV

  • But not really
  • Another way of thinking about stateful UI
  • Facilitates some interesting patterns
  • Powerful abstractions
  • Supports universal rendering OOTB

Using React to make awesome stuff

A Closer Look

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Components

 JSX

It's all JavaScript

  • Just a transform (like CoffeeScript)
  • No crippled templating language
  • Separation of concerns (not technologies)
  • Does not emulate HTML 100% (some gotchas)
  • Optional (but highly encouraged)
var HelloWorldComponent = React.createClass({
  
  render: function() {
    return (
      React.createElement("div", { className: "some-style" },
        React.createElement("p", null, "Hello World");
      );
    );
  }

});

Without JSX

ReactDOM.render(
  <HelloWorldComponent/>,
  document.querySelector('#mountNode');
);

Mouting into the DOM

That's all nice

But what about state, changes and everything that makes my app dynamic?

Props and State

Using Props

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

Passing Props

<HelloWorldComponent greeting='Hello World' />
<HelloWorldComponent greeting={'Hello ' + 'World'} /> 
<HelloWorldComponent greeting={getGreeting()} />

State

Initial State

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Updating State

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Events

  • Synthetic
  • Declarative

Event Handlers

class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

Event Handling

var HelloWorldComponent = React.createClass({
  getInitialState: ...

  handleClick: function (event) {
    event.preventDefault();

    this.setState({
      count: this.state.count + 1
    });
  },

  render: ...
});

Event Types

DOM Events

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
  }

  componentWillUnmount() {
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Composition

Composition

<ChatApp />

<FriendList />

<MessageList />

<Friend />

<Friend />

<Friend />

<Friend />

<Message />

<Message />

<Message />

<MessageInput />

Composition

var ChatApp = React.createClass({
  ...

  render: function() {
    return (
      <div>
        <FriendList friends={this.state.friends} />
        <MessageList messages={this.state.messages} />
        <MessageInput handleInput={this.handleInput} />
      </div>
    );
  }

});

Composition

var MessageList = React.createClass({
  render: function() {
    var messages = this.props.messages.map(function(message) {
      return (
        <Message
          content: message.content,
          from: message.from
        />
      );
    });

    return <ul>{messages}</ul>;
  }
});

Composition

var Message = React.createClass({
  render: function() {
    return (
      <li>
        <span>From: {this.props.from}</span>
        <span>Content: {this.props.content}</span>
      </li>
    );
  }
});

Composition

But where should i put all my state and stuff..?

Composition

<ChatApp />

<FriendList />

<MessageList />

<Friend />

<Friend />

<Friend />

<Friend />

<Message />

<Message />

<Message />

<MessageInput />

this.state.friends

this.state.messages

this.handleInput

this.props.friends

this.props.messages

this.props.handleInput

Data Flow

So won't this turn into a mess when my app grows in complexity..?

Flux / Redux

Unidirectional Data Flow

Flux

Flux

Integration with existing libraries

Backbone

backbone-react-component

react-backbone

backbone-react-component

// create component
var MyComponent = React.createClass({
  mixins: [Backbone.React.Component.mixin],
  render: function () {
    return <div>{this.state.model.foo}</div>;
  }
});

// create model
var model = new Backbone.Model({foo: 'bar'});

// render component and pass model as prop
React.render(<MyComponent model={model} />, document.body);

// update the UI
model.set('foo', 'Hello world!');

Angular

ngReact

ngReact

link: function(scope, elem, attrs) {
  //...

  scope.$watch(attrs.props, function() {
    React.render(<MyComponent scope={scope} />, elem[0]);
  }, true);

  scope.$on('$destroy', function() {
    React.unmountComponentAtNode(elem[0]);
  });
}

jQuery

Interacting with the DOM through

  • refs
  • ReactDOM.findDOMNode

jQuery

var MyComponent = React.createClass({

  componentDidMount: function() {
    var node = React.findDOMNode(this.refs.myContainer);
    var $node = $(node);
    // manipulate the node
  },

  componentDidUpdate: function() {
    var node = React.findDOMNode(this.refs.myContainer);
    var $node = $(node);
    // manipulate the node
  },

  componentWillUnmount: function() {
    // clean up if necessary
  },

  render: function() {
    return <div ref='myContainer'>Hello World</div>;
  }

});

om -  ClojureScript

(ns example
  (:require [om.core :as om]
            [om.dom :as dom]))

(defn widget [data owner]
  (reify
    om/IRender
    (render [this]
      (dom/h1 nil (:text data)))))

(om/root widget {:text "Hello world!"}
  {:target (. js/document (getElementById "my-app"))})

Targeting other platforms

React Canvas

React Canvas

<Surface>
<Layer>
<Group>
<Text>
<Image>
<ListView>

<div>
<span>
<p>
<ul>
<li>
<table>

vs.

React Native

React Native

<Image>
<ListView>
<MapView>
<Navigator>
<ScrollView>
<Text>
<TextInput>
<View>
<WebView>

...

<div>
<span>
<p>
<ul>
<li>
<table>

vs.

Other Targets

  • Desktop
  • Terminal (blessed)
  • ThreeJS

Pretty much anything!

Learn once - Write anywhere

Write once - Deploy anywhere

Development Tools

Real world examples

  • Facebook
  • Netflix
  • Instagram
  • SOL
  • Flipboard

Takeaways

  • Different way of thinking
  • It's just JavaScript, and it's really fast
  • Stop fighting imperative stateful API's and build declarative apps with React
  • Composition is king
  • There has never been a better time to be a JS dev

Questions?

Shameless plugs

React Workshop - May 6-7.

NDC Training

NDC

Building Isomorphic Apps in JavaScript

Talk - June 19.

30 Hours React JS Course - #03

By Tarun Sharma

30 Hours React JS Course - #03

Talk for NDC Meetup

  • 582