Chapter 5. Use Your React Components with Another Library

React is a great library used for building user interfaces. What if we want to integrate it with another library that is responsible for receiving data? In the previous chapter, we outlined five tasks that our Snapterest web application should be able to perform. We decided that four of them were related to the user interface, but one of them was all about receiving data; receive tweets from the Snapkite Engine server in real time.

In this chapter, we'll learn how to integrate React with the external JavaScript library and what React component lifecycle methods are, all while solving the very important task of receiving data.

Using another library in your React component

As we discussed earlier in this book, our Snapterest web application will consume a live stream of tweets. In Chapter 1, Installing Powerful Tools for Your Project, you installed the Snapkite Engine library that connects to the Twitter Streaming API, filters the incoming tweets, and sends them to our client application. In turn, our client application needs a way of connecting to that live stream and listening for the new tweets.

Luckily, we don't need to implement this functionality ourselves because we can reuse another Snapkite module called snapkite-stream-client. Let's install this module.

Navigate to the ~/snapterest directory and run the following command:

npm install --save snapkite-stream-client

It will install the snapkite-stream-client module, and add it to package.json as a dependency.

Now we're ready to reuse the snapkite-stream-client module in one of our React components.

In the previous chapter, we created the Application component with two child components: Stream and Collection. In this chapter, we'll create our Stream component.

Let's start by creating the ~/snapterest/source/components/Stream.react.js file:

var React = require('react');
var SnapkiteStreamClient = require('snapkite-stream-client');
var StreamTweet = require('./StreamTweet.react');
var Header = require('./Header.react');

var Stream = React.createClass({

  getInitialState: function () {
    return {
      tweet: null
    }
  },

  componentDidMount: function () {
    SnapkiteStreamClient.initializeStream(this.handleNewTweet);
  },

  componentWillUnmount: function () {
    SnapkiteStreamClient.destroyStream();
  },

  handleNewTweet: function (tweet) {
    this.setState({
      tweet: tweet
    });
  },

  render: function () {
    var tweet = this.state.tweet;

    if (tweet) {
      return (
        <StreamTweet
        tweet={tweet}
        onAddTweetToCollection={this.props.onAddTweetToCollection} />
      );
    }

    return (
      <Header text="Waiting for public photos from Twitter..." />
    );
  }
});

module.exports = Stream;

First, we will import the following modules that our Stream component depends on:

  • React: This is a React library
  • StreamTweet and Header: These are React components
  • snapkite-stream-client: This is a utility library

Then, we will define our React component. Let's take a look at the methods that our Stream component implements:

  • getInitialState()
  • componentDidMount()
  • componentWillUnmount()
  • handleNewTweet()
  • render()

We're already familiar with the getInitialState() and render() methods; they are part of React's API. You already know that any React component must implement at least the render() method. Let's take a look at the render() method of our Stream component:

render: function () {
  var tweet = this.state.tweet;

  if (tweet) {
    return (
      <StreamTweet
      tweet={tweet}
      onAddTweetToCollection={this.props.onAddTweetToCollection} />
    );
  }

  return (
    <Header text="Waiting for public photos from Twitter..." />
  );
}

As you can see, we created a new tweet variable that references the tweet property, which is part of a component's state object. We then check whether that variable has a reference to an actual tweet object, and if it does, our render() method returns the StreamTweet component, or else, it returns the Header component.

The StreamTweet component renders a header and the latest tweet from a stream, whereas the Header component renders only a header.

Have you noticed that our Stream component doesn't render anything itself, but rather returns one of the two other components that do the actual rendering? The purpose of a Stream component is to encapsulate our application's logic and delegate rendering to the other React components. In React, you should have at least one component that encapsulates your application's logic, stores, and manages your application's state. This is usually a root component or one of the high-level components in your component hierarchy. All the other child React components should have no state if possible. If you think of all the React components as Views, then our Stream component is a ControllerView.

Now that we know what a Stream component renders, let's discuss it in the other methods:

getInitialState: function () {
  return {
    tweet: null
  }
},

The getInitialState() method returns the initial state object with a tweet property, which is set to null. Our Stream component will receive an endless stream of new tweets, and it needs to re-render its child components every time a new tweet is received. In order to achieve this, we need to store the current tweet in the component's state. Once we update its state, React will call its render() method and re-render all of its child components. For this purpose, we will implement the handleNewTweet() method:

handleNewTweet: function (tweet) {
  this.setState({
    tweet: tweet
  });
},

The handleNewTweet() method takes a tweet object, and sets it as a new value for the component state's tweet property.

Where does that new tweet come from and when does it come? Let's take a look at our componentDidMount() method:

componentDidMount: function () {
  SnapkiteStreamClient.initializeStream(this.handleNewTweet);
},

This function calls the initializeStream() method of the SnapkiteStreamClient object, and passes a this.handleNewTweet callback function as its argument. SnapkiteStreamClient is an external library with an API that we're using to initialize a stream of tweets. The this.handleNewTweet function will be called for every tweet that SnapkiteStreamClient receives.

Why did we name this method componentDidMount()? We didn't. React did. In fact, the componentDidMount() method is part of React's API. It's one of the React component's lifecycle methods. It's called only once, immediately after React has finished the initial rendering of our component. At this point, React has created a DOM tree, which is represented by our component, and now we can access that DOM with another JavaScript library.

componentDidMount() is a perfect place for integrating React with another JavaScript library. This is where we connect to a stream of tweets using the external SnapkiteStreamClient library.

Now we know when to initialize the external JavaScript libraries in our React components, but what about the reverse process—when should we uninitialize and clean up everything that we've done in the componentDidMount() method? It's a good idea to clean up everything before we unmount our components. For this purpose, React API offers us another component lifecycle method—componentWillUnmount():

componentWillUnmount: function () {
  SnapkiteStreamClient.destroyStream();
}, 

The componentWillUnmount() method is called by React just before React unmounts the component. As you can see in the componentWillUnmount() method, you're calling the destroyStream()method of the SnapkiteStreamClient object. destroyStream() cleans up our connection to SnapkiteStreamClient, and we can safely unmount our Stream component.

You might be wondering what are the component lifecycle methods and why do we need them?

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

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