React: Thinking in Self Contained Components

This is a post that will get you start with React. It is intended for server-side developers with basic JavaScript or JQuery experience, for Angular developers and for web developers in general without knowledge in React. Basically, that is me, a server-side developer with JQuery and Angular experience. I’m very far to be a React expert. I was curious about React but what makes me to start learning was React Native (build once, in JavaScript/React Design, then, deploy in Android and iOS, real native mobile apps). To begin with, I decided to start with plain React and after that continue with React Native. I have to say that I liked React, a lot! It is a great library created to build real Object Oriented Designs on Web UI. This post is a brief of what I think you have to know to start developing with React.

I will start talking a bit about React’s spirit and why it was created. Then I will follow with their few main concepts that you must understand to build applications with React. And finally, I will explain how I built a pretty small React application called react-simple that helped me to put in practice what I have read.

Object Oriented Style

React is a JavaScript library for building user interfaces. It was created by Facebook developers. ¿Why not use one of the many existing JavaScript libraries or frameworks instead of create another one? Well, they think that existing ones are unnecessary complex and doesn’t help with maintainability for big front-end applications (like Facebook). So, they came up with a way to build and communicate self-contained UI components.

The first great thing that React gives you is a way to build small loosely coupled components to create User Interfaces. The really (seriously really) hard thing, as always, is Design!. I mean, how you should break a User Interface in small reusable components? There is a nice tutorial that helps specifically on this: Thinking in React.

The other great thing that React gives you is the rendering system, which takes care of DOM. You don’t need to manipulate the DOM yourself. React’s rendering system will do that for you thanks to a mechanism called Virtual DOM. When the internal state of a component change, it is re-painted on the screen by the rendering system. Pretty match like an observer pattern (or before that, like the Dependency Mechanism of the MVC implementation that comes with Smalltalk). But in contrast to the Observer Pattern, React’s Components are the observer and the observable, that responsibility is not separated. The Components contain the state and the markup to paint that state on the screen. Do you see how nice is this? This is against many well known development styles where User Interface markup is on a template and gets mixed with state to be painted on the screen. Usually, this is done on Controllers, where state comes from Models and UI from templates Views. Sounds like MVC right? Well, React mindset is pretty different to this.

React’s Main Concepts

There are few, but very important concepts that you have to understand. I will describe them as an introduction to the next section, in which I present a simple React application.

  • Component-driven Design:

    As mentioned, the component is the primary syntactical construction of React used to create user interfaces. React’s components interface requires you to implement a single method called render. The responsibility of the component’s render method is to paint itself on the screen.

  • Properties and state:

    React’s components encapsulates properties (props) and state. When any of these change, the component is re-painted on the screen. Properties are passed as arguments from components when creates (or instantiates) other components (in a parent/child relationship). They are read-only, they cannot change after the component is created. State is a special property which is mutable and is created and maintained inside de component. Once the component is created, you might want to change their state, in order to re-paint the component on the screen. This is where the state property is used. A typical use case is when your component gets data from a remote end point (making an Ajax call) and make changes to the State and that trigger the component to be re-painted.

  • Rendering System:

    The rendering system is the mechanism that keep observing the special state property to trigger the call to the render method when it change (along with other hook methods from the life cycle, see below). So, we can say that React’s components provides a kind of observer / observable (or subject) mechanism, but these two responsibilities resides inside the same object (or component). As you might have guessed, the render produce changes on the DOM. To implement this automatic update of the DOM, React use a data structure in memory called Virtual DOM, which is synced with the real DOM. While the algorithm is different, you can say that this process is similar to what ORMs do to keep the in memory objects in the persistence context synced with the persistent storage.

  • Component’s Life Cycle:

    React’s components follows a defined life cycle triggering events at certain moments depending on what the component has done or will do. The events are grouped in categories, which are three: Mounting (an instance of a component is attached to the DOM), Updating (The component is updated as a result of a change in props or state), UnMounting (When an instance of a component is detached from the DOM). The following table shows the sequence of life cycle events, grouped by category, illustrating which of them depends on changes on props and state. While is not an event, I’m adding the constructor to the table. The events function are shown in the order in which they are executed by React.

    Life Cycle Table
    Category Event Functions
    Mounting constructor(), componentWillMount(), render(), componentDidMount()
    Updating Props componentWillReceiveProps(), shouldComponentUpdate(), componentWillUpdate(), render(), componentDidUpdate()
    Updating State shouldComponentUpdate(), componentWillUpdate(), render(), componentDidUpdate()
    UnMounting componentWillUnmount()
  • JSX:

    JSX means JavaScript XML. It is an XML-like markup to describe the User Interface. This markup will end up creating instances of React Elements and Components. You will see that React Elements generally match with those found in HTML. More about JSX on the next section.

React-Simple Application

In this section I will go through react-simple, a basic application to put in practice the concepts I described in the previous section. I will explain how to download and run react-simple and then show the components and its communications in order you can see the concepts implemented.

Clone, Install and Start

Firstly you should clone the repo, install the dependencies of the project and start it (You will need to have installed: git, nodejs and npm. And this process will require a github account).

> git clone https://github.com/enriquemolinari/react-simple.git
> cd react-simple
> npm install
> npm start

This will start the application in Nodejs, by default on port 3000. If you go to http://localhost:3000/, you should see a NavBar with the users link. See the picture below:

Users Table

If you click on the “More…” button you will see a fake details of the user, see below:
User Detail

This application use react-bootstrap and react-spinners. It also use a free and online Random User API and to make ajax calls the Fetch API which is implemented in most of the browsers today.

Source Code

As mentioned, React applications can be built from many small components and those components communicates as a consequence of instantiation or event handling (button clicks, links, etc). Each React application can be seen as a tree structure of components. I will start describing the components that form the application, and then I will explain the most important lines of code of each component.

Below you will see the tree relationship of components I wrote for the react-simple application.

     -   App.js  -
    /              \  
MenuHeader.js  UserTable.js
                   |
             UserDetailModal.js
                   |
               UserDetail.js

To compare with what you would do in Java, since React’s style is very object oriented, our application main’s method would be launched in this way, just to give you other view of how this application is designed.

class Main {
 public static void main(String[] args) {
    App app = new App(
                    new MenuHeader(...), 
                    new UserTable(
                          new UserDestailModal(
                               new UserDetail(...)
                          )
                    )
              );
    app.render(); 
 }
}

The explanation of the source code follows the tree structure of components in preorder. In the source code below you will see more components in JSX markup. They belong to the dependencies of react-simple, like react-bootstrap and react-spinners.

index.html: This is just a simple html template where the main div container resides at line 17.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">

    <!-- Bootstrap css files -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <title>React Simple</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>

index.js: This is the “main” method, the entry point, that render the root component, App, inside the div id=root container. Note that <App /> is the way to instantiate a component in JSX markup.

ReactDOM.render(<App />, document.getElementById('root'));

App Component: Here is our root component, that is why it is called “App”. Or in terms of an Object Oriented Programming, this is our system object that will delegate on other object. Inside the render method we have the MenuHeader component being instantiated using JSX. As a parameter, property in React’s world, we are passing a function called usersItemMenuClicked(). This function is received in the MenuHeader component as a property, acceded using this.props.usersItemMenuClicked. After that, in a conditional expression you see the UserTable component. Then, if we run this application, the App#render() will instantiate the MenuHeader and as described above, it will trigger the MenuHeader#constructor and then the MenuHeader#render(). Those methods are the only ones implemented in MenuHeader.js, see below. And finally it will also paint the text: ‘Please, use the Users menu…’.

class App extends Component {
  constructor(props) {
    super(props);
    this.usersItemMenuClicked = this.usersItemMenuClicked.bind(this);
    this.state = {
          userTableClicked : false
    };
    this.apiurl = 'https://randomuser.me/api/';
 }

  render() {
    return (
      <div>
        <MenuHeader usersItemMenuClicked={this.usersItemMenuClicked}/>
        {
          this.state.userTableClicked ?
            <UserTable apiurl={this.apiurl}/>
            :
            'Please, use the Users menu...'
        }
      </div>
    );
  }

  usersItemMenuClicked() {
    this.setState({userTableClicked : true});
  }
}

MenuHeader Component: This is the component that render a NavBar (a react-bootstrap component) on the screen. If you see at line 23, there is an onClick event declared which will execute the handleClick instance method. If you see the implementation of that method at line 8, you will see that it is calling the function received as a parameter from the parent component App. And here is when the magic of React start. If the menu item is clicked, it will call the method App#usersItemMenuClicked in the parent component, which change an state property called this.state.userTableClicked. As described in the life cycle table above, this will make to trigger the App#render() method as we changed the state property owning by the App component. And that execute MenuHeader#render() (as is already there, that part on the real DOM is not updated since it will match with the one on the Virtual DOM), and instantiate the UserTable component. Lets continue there.

class MenuHeader extends Component {
  constructor(props, context) {
    super(props, context);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.usersItemMenuClicked();
  }

  render() {
    return (
      <div>
        <Navbar inverse collapseOnSelect>
          <Navbar.Header>
            <Navbar.Brand>
              <a href="http://copypasteisforword.com">React Simple</a>
            </Navbar.Brand>
            <Navbar.Toggle />
          </Navbar.Header>
          <Navbar.Collapse>
            <Nav>
              <NavItem eventKey={1} href="#" onClick={this.handleClick}>
                Users
              </NavItem>
              <NavItem eventKey={2} href="#">
                Other Item ...
              </NavItem>
            </Nav>
          </Navbar.Collapse>
        </Navbar>
      </div>
    );
  }
}

UserTable Component: This component knows how to bring users from the Random User API, using the Ajax Fetch API. This is done from two life cycle functions, componentDidMount(), on line 21 and componentWillReceiveProps(), on line 26. As described in the Life Cycle Table in the previous section, the first time you click on the Users menu item, the constructor(), and then render() are executed. At this point, we have the state property this.state.users initialized with an empty array, so you will only see the html table header on the page. The life cycle execution chain continue right after that, with the componentDidMount(), consuming the random users API and changing the this.state.user property, which will trigger the render() method again. This will end up painting the html table with 10 users.

Any other time you click on the Users menu item, since the UserTable component is already mounted and we are passing a property to it, the Update Props category is being executed, calling the componentWillReceiveProps() method bringing another random page of 10 users, which change the this.state.users property producing a call to the render() method again.

After rendering users, comes the instantiation of the UserDetailModal component, with a conditional based on a button click and a change in a state property owned by this component. The open button belongs to the UserTable component, but the close button belongs to the UserDetailModal component. However, the property this.state.showModal is owned by the UserTable component, so that component is the resposible to show and hide the modal window. Note that the UserDetailModal receives as a property (handleClose) an anonymous function from the UserTable component that is executed on the close event but in the context of the UserTable component.

class UserTable extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
            users: [],
            loading: false,
            error: false,
            errorMsg: '',
            showModal: false
          };
  }

  bringUsers() {
    this.setState({loading: true});
    fetch(this.props.apiurl + '?results=10')
    .then((resp) => resp.json())
    .then((users) => this.setState({users: users.results, loading: false}))
    .catch((error) => this.setState({error: true, errorMsg: error.error, loading: false}));
  }

  componentDidMount() {
    this.bringUsers();
  }

  //Needed for bringing another 10 users if menu item is clicked after mounted
  componentWillReceiveProps() {
    this.bringUsers();
  }

  render() {
    if (this.state.error) {
      return (
        <Alert bsStyle="danger">
          <strong>Ups...</strong> something went wrong ({this.state.errorMsg})
        </Alert>
      )
    }
    return (
      <div>
        <div>
          <BarLoader color = {'#123abc'} loading = {this.state.loading} />
          <Table striped bordered condensed hover>
            <thead>
              <tr>
                <th>#</th>
                <th>Gender</th>
                <th>Name</th>
                <th>email</th>
                <th>actions</th>
              </tr>
            </thead>
            <tbody>
              {
                this.state.users.map((item, key) =>
                  <tr key={key}>
                    <td>{key}</td>
                    <td>{item.gender}</td>
                    <td>{item.name.first} {item.name.last}</td>
                    <td>{item.email}</td>
                    <td><Button href="#" onClick={() => this.setState({showModal: true})}>More...</Button></td>
                  </tr>
                )
              }
            </tbody>
          </Table>
        </div>
        { (this.state.showModal) ?
             <UserDetailModal
                  apiurl={this.props.apiurl}
                  show={this.state.showModal}
                  handleClose={() => this.setState({showModal: false})}/>
        : ''
        }
      </div>
    );
  }
}

UserDetailModal Component: When the button “More…” on the UserTable parent component is clicked, this component is mounted, executing the life cycle as explained in the previous section, bringing a random user on the componentDidMount() method, changing the this.state.user property, which trigger the render() method which now open a modal window instantiating the UserDetail component. The close event in this component change the state on the parent component (UserTable.state.showModal) triggering the UserTable#render(), which will paint the table of users but now without the modal, causing the unmounting of the UserDetailModal component. Note again that the table of users in the real DOM is not re-painted, since the Virtual DOM and the real DOM are identical there.

class UserDetailModal extends Component {
  constructor(props, context) {
    super(props, context);
    this.handleClose = this.handleClose.bind(this);
    this.state = {
            user: null,
            loading: false,
            error: false,
            errorMsg: '',
          };
  }

  componentDidMount() {
    this.setState({loading: true});
    fetch(this.props.apiurl) // Simulate getting details from a user selected
    .then((resp) => resp.json())
    .then((user) => this.setState({user: user.results, loading: false}))
    .catch((error) => this.setState({error: true, errorMsg: error.error, loading: false}));
  }

  handleClose() {
    this.props.handleClose();
  }

  render() {
    if (this.state.error) {
      return (
        <Alert bsStyle="danger">
          <strong>Ups...</strong> something went wrong ({this.state.errorMsg})
        </Alert>
      )
    }
    return (
      <div>
        <Modal show={this.props.show}>
          <Modal.Header>
            <Modal.Title>User Detail</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            {
                (this.state.user) ? <UserDetail details={this.state.user[0]}/>
                                   : <BarLoader color = {'#123abc'} loading = {this.state.loading} />
            }
          </Modal.Body>
          <Modal.Footer>
              <Button onClick={this.handleClose}>Close</Button>
          </Modal.Footer>
        </Modal>
      </div>
    );
  }
}

UserDetail Component: This is a stateless component. There is no state declared, only a prop with a user object that is painted on the screen.

class UserDetail extends Component {

  render() {
    let details = this.props.details;
    return (
      <div>
        <p><img src={details.picture.thumbnail} alt="user fake face"/></p>
        <p><b>First Name: </b>{details.name.first}</p>
        <p><b>Last Name: </b>{details.name.last}</p>
        <p><b>Id: </b>{details.id.name} {details.id.value}</p>
        <p><b>Address: </b>{details.location.street} ({details.location.city} {details.location.state})</p>
        <p><b>Phone: </b>{details.phone}</p>
        <p><b>Cell: </b>{details.cell}</p>
      </div>
    );
  }
}

And that is it. See how interesting is this? Self-contained components that knows how to get the data and knows how to paint itself on the DOM when the internal state change. Pretty nice, right? I hope this can help understand better React’s concepts. It is a different approach to build JavaScript front-ends, with a well known design mindset, but with an innovative rendering system which takes care of the DOM.

Posted in Frameworks