What I have learned so far in React

What I have learned so far in React

As many of you already know, React is a Javascript library developed and maintained as open source by Facebook, and it’s sole purpose is to create composable and reusable user interfaces (a.k.a. components).

If you are familiar with all the popular frameworks such as Angular, Ember, Backbone, which are using the MV* pattern to separate concerns in an application, you must know from the beginning that React is the view of your application, which are in fact, your components. React seems to have figured this out very well and it’s doing a fine job in managing components and their state.

Even if it’s the V in your application, this doesn’t mean you can’t develop scalable and performant applications in React. The best part in my opinion is that you are free to create your own stack of solutions for your application, meaning you can use whatever things you’re already comfortable with. But if you want to take full advantage of its unique perspective of developing applications, you should go along with Flux, which is an application architecture also developed by Facebook, to go hand in hand with React in a very swift manner. The only thing you would further need for your stack is a way to persist your data, with a NoSQL database solution, such as MongoDB, let’s say, and you’re ready to start playing. You can use no database at all if you’re just testing out the capabilities of React and Flux, you can just throw some arrays of values.

Before we start, keep in mind I am not going to talk about Flux in this post, I’m only focusing on React.

A lot of you these days are hearing more and more about web componentsshadow DOM, and other stuff related to them, and you’re probably asking yourself what’s all about with this stuff anyway. The idea in components is to have them encapsulated, with everything they need, ready to be used and reused at any time in any context. You are already seeing components in Angular directives and many other frameworks and libraries, but in React, a component is much more grounded and visible than anywhere else. In a React component you have the component’s markup, its various states, and all the other logic used for interactivity, which is not related to data persistency (this is the job of stores, the ‘model’ used in Flux). The only thing you don’t have is its styling, but this can also be achieved if you don’t mind using inline CSS, such as exemplified in this great solution from FormidableLabs, or this one from one great guy from Facebook, Christopher Chedeau (Vjeux), who is already using this approach on their own projects.

To create an easy way to deal with your components, the guys from Facebook also created a nice way to write your components, by using JSX, which is a suggaring tool to write more easy and visible your components. In order to use JSX, you must include in your project, aside from the React library, the JSX Transformer, which will compile your JSX files into plain JS files. In order to compile your files and watch over them for changes, you can implement this simple React tool. Or you can implement a nice build for yourself with gulp and browserify, for both development and production mode. But I think for just playing around with React you can simply put your JSX code inside of your main HTML file and having the JSX Transformer included, you will easily have your code in-browser transformed.

React components are rerendered every time their state is changing. But because React is using a performant Virtual DOM, which is actually a reflection of the real DOM in its various states in time, but performing at fast speeds, since it’s composed by pure Javascript internals. We all know DOM is rendering slow, but with the Virtual DOM we don’t have to worry about this, it’s way faster and it proved to be performant even in big applications with a lot of nodes. Every time we change a state, that change is reflected into our DOM by diff-ing the previous state of the DOM with the new one and ONLY what changed is pushed into the current state, meaning the DOM is not rerendered entirely.

Now let’s get to the real deal and show some things I’ve learned so far by playing with React.

A basic component in React is looking like this:

var MyComponent = React.createClass({  
  getDefaultProps: function() {
    return {
        name: "Ionut"
    }
  },
  getInitialState: function(){
    return {
      inputDefaultValue: 'change me'
    }
  },
  handleChange: function(event) {
    this.setState({
        inputDefaultValue: event.target.value
    });
  },
  handleClick: function(event) {
    this.setState({
        inputDefaultValue: ""
    });
  },
  handleButtonClick: function(event) {
    var textField = React.findDOMNode(this.refs.myTextInput);
    textField.focus();
    this.setState({
        inputDefaultValue: ""
    });
  },
  render: function() {
    return (
      <div className="my-component">
        Hello {this.props.name}! I am a Component.
        <input type="text" value={this.state.inputDefaultValue} ref="myTextInput" onChange={this.handleChange} onClick={this.handleClick} />
        <button onClick={this.handleButtonClick}>click to focus</button>
      </div>
    );
  }
});
React.render(  
  <MyComponent name="Alin" />,
  document.getElementById('reactApp')
);

This is a simple component in React which returns a simple text in a specific HTML node. I’ve written the component with more attributes and methods intentionally, because I want to talk about them around this example. Now let’s dissect a little bit the code, and see what we got:

We create our component by using a constructing function named createClass and passing to it an object literal, with attributes and methods. Some of the methods are from the React library, such as getInitialStategetDefaultPropsrender, but you can declare as many useful methods in here you want, in order to manipulate your component as you like. The most important method from here is the render method, which is returning your component’s actual body. Though that markup looks like HTML, it’s not, it’s actually a way in which React is sugaring functions in order to keep our component more visible and easy to deal with (especially by designers, those who don’t have technical background in Javascript), and those attributes are actually functions arguments.

After you created your component, it’s time to render it to your DOM. This is done by using the React.render API method, which is requiring two arguments to be passed, the first one being the actual component and the second one is used to specify the DOM node in where we’re going to render our component.

Our component example is a simple one, but we must understand some things that it’s using.

Your component must have an initial state (which can and will change) with initial data (that is not changing). The initial data is what we are calling props in React. To find more about props you can check out the official documentation of React in here. State is representing data that will change over time, so what you think it will change in your application must be expressed as state. You can read more about states in here. So our components will be stateful machines, with an initial state declared from the start in the getInitialState method. The method getDefaultProps is used to define our default props, which is the initial data passed into our component. Props are usually used to pass data from the parent component to its children components.

So you can have children components inside your parent component like this:

// The render method inside your Parent Component 'MyComponent'
render: function() {  
  return (
    <div className="my-component">
      <ChildComponent /> // The child component
    </div>
  );
}

and the child component body is this:

var ChildComponent = React.createClass({  
    render: function() {
        return (
            <div className="child-component">
              Hello {this.props.name}! I am a Component.
              <input type="text" value= {this.state.inputDefaultValue} ref="myTextInput" onChange={this.handleChange} onClick={this.handleClick} />
              <button onClick={this.handleButtonClick}>click to focus</button>
            </div>
        );
    }
});

So you can compose your components by using components inside other components, making your components reusable in many places. Because we’re talking of reusability, React comes with another great thing called mixins, which are objects containing common reusability code, which you can then include it where you need it. You can learn more about mixins in here.

We also use className attribute on our React nodes, because identifiers such as class are discouraged as XML attribute names, since JSX is XML-like-ish.

We use setState to change the state of our component, changing whatever is changeable in our component, the rest lying in our props.

As you can see on our text input field, we use event props such as onChange and onClick, passing the event handler we delegate for that specific job, in order to trigger it. Speaking of inputs, I must tell you that in React there are 2 types of components: controlled and uncontrolled. The controlled components are those components in where their attributes values such as value are reflecting the actual passed value and you cannot change the value in your browser if you click on your text input and start typing. Only events such as onChange can manipulate that value. On the other hand, the uncontrolled components are those components that are missing such attributes such as value or set it to be null. If you want to supply your text field with some value, you can use the defaultValue prop. You can read more about controlled and uncontrolled components in here.

Also, a React component has different life cycles, which are generally used with callbacks to do different things in the different ‘living’ states of the component. You can learn more about them in here.

Now that we’ve got into some aspects of React components, I want to show you some few other tips and what you should be aware of when developing with it:

  • in the render method, you should always return a single main node of your component’s body; you cannot return multiple node on the main level, you must put inside that single node all your markup;
  • also, in the same render method, at the return, it’s better to create a visible and organized hierarchy of your markup, just like you do in HTML, like this:
render: function() {  
    return (
        <div className="the-returned-single-node">
            // Other markup in here
        </div>
    );
}

not like this:

render: function() {  
    return (<div className="the-returned-single-node">// Other markup in here</div>);
}

in where you don’t have visibility of your nodes;

  • don’t use values that will change in time as props, use them as states;
  • the best place to load your initial data is in the componentDidMount method, and when the response arrives, store it in the state and trigger a render to update your UI by passing in some of the updated values from state;

I really see a nice future in this direction taken by Facebook with web development and I am really excited how things are evolving so far, and that I finally have picked up for learning and future projects a very good library such as React + a nice application architecture such as Flux.

 

Post Comment