Component attributes (props)

Props are the way to pass down data from a parent to a child component in React.

For this next example, we want to change the InvestmentListItem component to render the value of the roi variable formatted in percentage.

To implement the next specs, we are going to use a few helper methods that React offers through the React.addons.TestUtils object, as follows:

describe("InvestmentListItem", function() {
  var TestUtils = React.addons.TestUtils;

  describe("given an Investment", function() {
    var investment, component;

    beforeEach(function() {
      investment = new Investment({
        stock: new Stock({ symbol: 'peto', sharePrice: 0.25 }),
        shares: 100,
        sharePrice: 0.20
      });

      component = TestUtils.renderIntoDocument(
        <InvestmentListItem investment={investment}/>
      );
    });

    it("should render the return of investment as a percentage", function() {
      var roi = TestUtils.findRenderedDOMComponentWithClass(component, 'roi'),
      expect(roi.getDOMNode()).toHaveText('25%'),
    });
  });
});

As you can see, we are no longer using the setFixture method from the jasmine-jquery matcher. Instead, we are using the TestUtils module to render the component.

The biggest difference here is that TestUtils.renderIntoDocument doesn't actually render in the document, but it renders into a detached node.

The next thing you will notice is that the InvestmentListItem component has an attribute (actually called prop) where we pass down investment.

Then, at the spec, we are using another helper method called findRenderedDOMComponentWithClass to look for a DOM element in our component variable.

This method returns ReactElement. And again, we will use the getDOMNode method to get the actual DOM element and then use the jasmine-jquery matcher to check for its text value, as follows:

var roi = TestUtils.findRenderedDOMComponentWithClass(component, 'roi'),
expect(roi.getDOMNode()).toHaveText('25%'),

Implementing this behavior in the component is actually very simple:

(function (React) {
  var InvestmentListItem = React.createClass({
    render: function () {
      var investment = this.props.investment;

      return <li className="investment-list-item">
        <article>
          <span className="roi">{formatPercentage(investment.roi())}</span>
        </article>
      </li>;
    }
  });

  function formatPercentage (number) {
    return (number * 100).toFixed(0) + '%';
  }

  this.InvestmentListItem = InvestmentListItem;
})(React);

We can access any props passed to a component through the this.props object.

Expanding the original implementation, we've added a span element with the expected class from the spec.

To allow the return on investment to be dynamic, JSX has a special syntax. Using {}, you can invoke any JavaScript code in the middle of the XML. We are invoking the formatPercentage function while passing the investment.roi() value, as follows:

<span className="roi">{formatPercentage(investment.roi())}</span>

Again, just to make this clear, this JSX transformed into JavaScript would be:

React.createElement("span", {className: "roi"}, formatPercentage(investment.roi()))

It is important to know that a prop should be immutable. It is not the responsibility of a component to change its own prop values. You can consider a React component that has only props as a pure function, in that it always returns the same result value given the same argument values.

This makes testing very simple as there are no mutations or changes in the state to test a component.

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

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