Jim Cheung

React

ReactDOM.render(
  React.DOM.h1(null, "Hello World!"), 
  document.getElementById("app")
);

The API to create a new component looks like this:

var MyComponent = React.createClass({ 
  /* specs */
});

the only thing you must do is implement the render() method

var Component = React.createClass({ 
  render: function() {
    return React.DOM.span(null, "I'm so custom"); 
  }
});

you cannot return text.

ReactDOM.render(
  React.createElement(Component),
  document.getElementById("app")
);

React.createElement() is one way to create an “instance” of your component. Another way, if you’ll be creating several instances, is to use a factory:

var ComponentFactory = React.createFactory(Component);

ReactDOM.render(
  ComponentFactory(),
  document.getElementById("app")
);

Properties

var Component = React.createClass({ 
  render: function() {
    return React.DOM.span(null, "My name is " + this.props.name); 
  }
});

Passing the property when rendering the component looks like this:

ReactDOM.render(
  React.createElement(Component, {
    name: "Bob",
  }),
  document.getElementById("app")
);

Property types:

var Component = React.createClass({ 
  propTypes: {
    name: React.PropTypes.string.isRequired,
  },
  render: function() {
    return React.DOM.span(null, "My name is " + this.props.name);
  }
});

available types:

Object.keys(React.PropTypes).join("\n")

State

updating this.state directly can have unexpected behavior and you shouldn’t do it. Just like with this.props, consider the this.state object read-only.

Similarly to how properties are accessible via this.props, you access the state via the this.state object.

React updates the UI when setState() is called. This is the most common scenario, but there’s an escape latch, as you’ll learn later. You can prevent the UI from being updated by returning false in a special “lifecycle” method called shouldComponentUpdate().

var up = function(c) {
  return ReactDOM.render(c, document.getElementById('container'))
};

var t = React.createClass({
  getInitialState: function() {
    return {
      text: this.props.text
    }
  },
  _textChange: function(ev) {
    this.setState({
      text: ev.target.value
    })
  },
  render: function() {
    return React.DOM.div(null, React.DOM.textarea({
      value: this.state.text,
      onChange: this._textChange
    }), React.DOM.h3(null, this.state.text.length))
  }
});

up(t);

React uses camelCase syntax for the event handlers, so you use onClick instead of onclick.

If you need the original browser event for whatever reason, it’s available to you as event.nativeEvent, but it’s unlikely that you’ll ever need to go there.

While setState(obj) merges the properties of obj with those of this.state, replaceState() completely overwrites everything.

Mixin

var logMixin = {
  _log: function(methodName, args) {
    console.log(this.name + '::' + methodName, args);
  },
  componentWillUpdate: function() {
    this._log('componentWillUpdate', arguments);
  },
  componentDidUpdate: function() {
    this._log('componentDidUpdate', arguments);
  },
  componentWillMount: function() {
    this._log('componentWillMount', arguments);
  },
  componentDidMount: function() {
    this._log('componentDidMount', arguments);
  },
  componentWillUnmount: function() {
    this._log('componentWillUnmount', arguments);
  },
};

var TextAreaCounter = React.createClass({
  name: 'TextAreaCounter',
  mixins: [logMixin],
  // all the rest..
};