10/02/2015

Making Your First React Component (updated to v0.14.x)

Update: Fixed example with 0.14.x ReactDom format and to use states, not props.

In a world of Angulars and Embers, what is the point of a library that only provides a third of the MVC equation? React offers simplicity and a welcome decoupling of display and business logic. React is not an MVC framework, and in a breath of fresh air, it doesn't pretend to be. React is there to help build your display element, no more. This means it can be a View layer in any MVC application implementation or the display logic for a website. This form of flexibility can be very important for having a robust code base that can grow and change with the times.

This post isn't about comparing React to any other library and framework. I have 2 articles on the Band of Coders website doing a comparison. If you need to decide between frameworks and libraries, then check over there. The first post compares Angular to Ember.

We are going to use this space to walk through creating a simple React component. React has a shorthand called JSX that allows you to put html like tags into your Javascript. JSX is pretty easy to use, however it also adds a new step to the deployment process. The code must be run through a transformer like Babel before a browser can use it. Since this is a tutorial, there is no build process to transform the code. We will use the vanilla Javascript that the React transformer automatically creates. React can be written either way.


"An important consideration is how data flows in React."

An important consideration is how data flows in React. React components are built in a hierarchy, where the top component is the one directly called by the developer to be rendered. Other components are included in the render function of this root, and the children will have components included in their render function, and on and on down the chain. React component nesting should mirror the DOM as you expect to see it. Data must be handed into the root component to be passed down the chain through the renders. To avoid complex data management, React only supports one-way data binding.

In practical application, this means that fresh data is passed down into the component chain with every render. Two-way data binding in React can be implemented with helpers, but it is not the default. For example, adding text to a field would not cause the UI to update by itself. Nothing outside that field is automatically updated. The developer calls events inside of which they change the data. The data change then causes everything to potentially re-render from the root component down. It sounds like this would create a lot of extra work but React is built with functions to make these updates easy to manage. Managing what updates and what doesn't is managed by props, state, and life cycle events.

Understanding props and state is important to working with React. Props are considered immutable and shouldn't change. State is mutable but should only be used carefully. Props are passed into a component when it is being mounted or updated. If the component does not need anything in the props, then props should remain untouched, and the relevant pieces are passed down the hierarchy. If the component needs to change something in the data, then that data is moved into the state. The data is manipulated as needed and used in that component, or passed down as a prop to the next component. React components can trigger a UI change by using a component method called setState. setState will change the component's state and trigger a UI update.

Any part of the UI affected by the state change will be replaced all at once. All data worth keeping needs to be passed back to the application logic and passed back down the render chain.

Let's make a pretend sign up section to a newsletter web site. There will be some text, an input field, and a button to submit.

React is based on the concept of large components built from small pieces. In our example, we have 1 component made up of a text paragraph, an input field, and a button all wrapped in a div. If this were HTML, we would do something like:

  <div id="submitEmail">
    <p>Text</p>
    <input></input>
    <button disabled="true">Submit</button>
  </div>

In React's shorthand called JSX, it would be:

<div id="submitEmail">
  <p>{this.state.text}</p>
  <input disabled={this.state.disabled}></input>
  <button disabled={this.state.disabled}>{this.state.buttonLabel}</button>
</div>
We have replaced the html hard coded text with "this.state.x". This tells the React engine to replace that section with the value currently stored on the element's state object at the supplied key. For example, this.state.text means replace this with the current value stored on the state object at the "text" key/position.

Changing the JSX to vanilla is easy:

React.createElement("div", null,
     React.createElement("p", null, this.state.text),
     React.createElement("input", {
           id: "email",
           disabled: this.state.disabled
        }),
     React.createElement("button", {
           onClick: this.onClick,
           disabled: this.state.disabled
     }, this.state.label)
);
We accomplish the transformation by replacing the tags with React.createElement. The first parameter is the tag, the second is any properties, and the third is any children. The indented structure still closely resembles its HTML and JSX counterparts.


"Of course, there is a little more to it but the bulk of what is necessary is above."

Of course, there is a little more to it but the bulk of what is necessary is above. To complete the React element we need a new top level HTML element to inject our React code into, and a way to tell React what this HTML tag will be called. Firstly, let's add an HTML tag on the page for React to render into.

<div id="submitEmail"></div>

Secondly, we create a React class which is how React knows what to put into its rendering location:

var Subscribe = React.createClass({
  displayName: "Subscribe",

  render: function render() {
        return //Our react code from above goes here
    }
});

Finally, we let React know it is time to start rendering our new element. Data is also provided for the children in the React hierarchy. The class name is Subscribe so that will be the createElement used in the React.render call which starts this process. Data will be passed in as properties in the second parameter. Finally, we pass a DOM element into the React.render call to mark the injection point.

ReactDOM.render(React.createElement(Subscribe, {
    text: paragraph,
    buttonLabel: 'Submit',
    disabled: true
}), document.getElementById('submitEmail'));

Update (Thanks Mike Boutin): The JSX to render it would look like:

ReactDOM.render(<Subscribe 
  text={paragraph} 
  buttonLabel='Submit' 
  disabled={true} 
/>, document.getElementById('submitEmail'));

React always wants to start with one element on the document, and one React component class. Remember, that data passed in is attached to the props object. This is true no matter how deep you go in a React hierarchy. A child element will only have the data properties passed to it from the parent, and all that data will be available on the child's props object. This also important for when data changes. Data changes are applied starting at the top of the hierarchy. If you want an element lower down in the hierarchy to be dependent on certain data then it should be passed down in the properties from the parents above it.

The full example is in the fiddle below. The next post will enhance this example by adding an event and a data change.

The Fiddle: