Vaadin Elements - Integrations - React Integration

React Integration

The React library from Facebook easily integrates with web components. As long as you import required polyfills and add HTML imports for the elements you are using, you can simply start adding these custom elements to your JSX markup.

See also the Web Components page in React documentation.

Grid Example

react integration
Figure 1. React integration example using vaadin-grid

The example consists of two React components: UserApp and UserGrid. The UserGrid component wraps the vaadin-grid element and does all necessary initialization to display a list of random users. As React does not support custom attributes on standard elements, vaadin-grid DOM API cannot be fully utilized in the initialization. Fortunately, vaadin-grid also provides corresponding JavaScript APIs.

Selecting an item in the UserGrid is handled by the UserApp component. The selection is handled by displaying the photo of the selected user below the vaadin-grid.

The code below can be run and forked as a JSFiddle at https://jsfiddle.net/pw1nLaL8/2/.

// Create the UserGrid class
var UserGrid = React.createClass({
  render: function(){
    return (
      '<vaadin-grid></vaadin-grid>';
    )
  },

  componentDidMount: function() {
    var _this = this;
    var vGrid = ReactDOM.findDOMNode(this);

    // Let the mounted <vaadin-grid> upgrade
    (function wait() {
      if (vGrid.selection) {
        // Assign the data source
        vGrid.items = _this.items;
        vGrid.size = 1000;

        // Bind selection listener
        vGrid.addEventListener("selected-items-changed", _this.onRowSelect);

        var pictureRenderer = function(cell) {
          cell.element.innerHTML = "<img style='width: 30px' src='" + cell.data + "'></img>";
        };

        // Define columns
        vGrid.columns = [
          {name: "user.picture.thumbnail", width: 100, renderer: pictureRenderer},
          {name: "user.name.first"},
          {name: "user.name.last"},
          {name: "user.email"},
        ];

      } else {
        setTimeout(wait, 50);
      }
    })();
  },

  items: function(params, callback) {
    var url = 'https://randomuser.me/api?index=' + params.index + '&results=' + params.count;
    getJSON(url, function(data) {
      callback(data.results);
    });
  },

  onRowSelect: function(e) {
    var onUserSelect = this.props.onUserSelect;
    var index = e.target.selection.selected()[0];
    e.target.getItem(index, function(err, data) {
      onUserSelect(err ? undefined : data.user);
    });
  }
});

var UserApp = React.createClass({

  render: function() {
    var userImage;
    if (this.state.selected) {
      userImage = <img className="user-image" src={this.state.selected.picture.large} ></img>;
    }

    return (
      <div>
        <UserGrid onUserSelect={this.userSelect}></UserGrid>
        {userImage}
      </div>
    );
  },

  getInitialState: function() {
    return {};
  },

  userSelect: function(user) {
    this.setState({selected: user});
  }
});

HTMLImports.whenReady(function(){
  ReactDOM.render('<UserApp></UserApp>', document.getElementById('container'));
});