Our first React component

As stated in the introduction of this chapter, with React, you declaratively write the interface code through components.

The concept of a React component is analogous to the component concept presented in Chapter 3, Testing Frontend Code, so expect to see some similarities next.

With that in mind, let's create our very first component. To better understand what a React component is, we are going to use a very simple acceptance criterion and as usual start from the spec.

Let's implement "InvestmentListItem should render". It's very simple and not really feature oriented but is a good example to get us started.

With what we learned in Chapter 3, Testing Frontend Code, we could start coding this spec by creating a new file called InvestmentListItemSpec.js and save it in the components folder inside the spec folder:

describe("InvestmentListItem", function() {

  beforeEach(function() {
    // render the React component
  });

  
it("should render", function() {
    expect(component.$el).toEqual('li.investment-list-item'),
  });
});

Add the new file to the SpecRunner.html file, as already demonstrated in previous chapters.

At the spec, we are basically using the jasmine-jquery plugin to expect that the encapsulated DOM element of our component is equal to a specific CSS selector.

How would we change this example to be a test of a React component? The only difference is the API to get the DOM node. Instead of $element with a jQuery object, React exposes a function called getDOMNode() that returns what it states—a DOM node.

With that, we can use the same assertion as before and have our test ready, as follows:

it("should render", function() {
  expect(component.getDOMNode()).toEqual('li.investment-list-item'),
});

That was easy! So, the next step is to create the component, render it, and attach it to the document. That is simple as well; take a look at the following gist:

describe("InvestmentListItem", function() {
  var component;

  beforeEach(function() {
   
 setFixtures('<div id="application-container"></div>'),
    var container = document.getElementById('application-container'),

    var element = React.createElement(InvestmentListItem);
    component = React.render(element, container);
  });

  it("should render", function() {
    expect(component.getDOMNode()).toEqual('li.investment-list-item'),
  });
});

It might seem like a lot of code, but half of it is just boilerplate to set up a document element fixture that we can render the React component in:

  1. First, we use the setFixtures function from jasmine-jquery to create an element in the document with the application-container ID. Then, using the getElementById API, we query for this element and save it in the container variable. The next two steps are the ones specific to React:
    1. First, in order to use a component, we must first create an element from its class; this is done through the React.createElement function, as follows:
      var element = React.createElement(InvestmentListItem);
    2. Next, with the element instance, we can finally tell React to render it through the React.render function, as follows:
      component = React.render(element, container);
    3. The render function accepts the following two parameters:
      • The React element
      • A DOM node to render the element in
  2. As of now, the spec is complete. You can run it and see it fail, showing the following error:
    ReferenceError: InvestmentListItem is not defined.
  3. The next step is to code the component. So, let's feed the spec, create a new file in the src folder, name it InvestmentListItem.js, and add it to the spec runner. This file should follow the module pattern we've been using until now.
  4. Then, create a new class of component using the React.createClass method:
    (function (React) {
      var InvestmentListItem = React.createClass({
        
    render: function () {
          return React.createElement('li', { className: 'investment-list-item' }, 'Investment'),
        }
      });
    
      this.InvestmentListItem = InvestmentListItem;
    })(React);
  5. At the least, the React.createClass method expects a single render function that should return a tree of React elements.
  6. We use again the React.createElement method to create the element that is going to be the root of the rendering tree, as follows:
    React.createElement('li', { className: 'investment-list-item' }, 'Investment')

The difference from its previous usage in the beforeEach block is that here, it is also passing a list of props (with className) and a single child containing the text Investment.

We will get deeper into the meaning of the props parameter, but you can think of it as analogous to the attributes of an HTML DOM element. The className prop will turn into the class HTML attribute of the li element.

The React.createElement method signature accepts three arguments:

  • The type of the component that can be either a string representing a real DOM element (such as div, h1, p) or a React component class
  • An object containing the props values
  • And a variable number of children components, which in this case, is just the Investment string

On rendering this component (by invoking the React.render() method), the result will be:

<li class="investment-list-item">Investment</li>

This is a direct representation of the JavaScript code that generated it:

React.createElement('li', { className: 'investment-list-item' }, 'Investment'),

Congratulations! You've built your first fully tested React component.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset