Integrate jQuery UI autocomplete and React

You can integrate jQuery UI widgets and React by taking advantage of React lifecycle methods.

React will call a component function named componentDidMount after it creates the markup corresponding to the component. In this function, you can access the markup that React has created directly and modify in any way that you want, before anything else happens in the application. Therefore it is the ideal place to initialise the jQuery UI autocomplete. You cannot initialise the autocomplete in render(), render() returns JSX nodes, which are JavaScript objects, but you need access to the real DOM node to initialise the autocomplete.

render: function() {
},

componentDidMount: function() {
  var tags = ['banana', 'strawberry', 'chocolate'];
  $(React.findDOMNode(this)).autocomplete({source: tags});
},

componentWillUnmount: function() {
  $(React.findDOMNode(this)).autocomplete('destroy');
}

We also define componentWillUnmount because we want to get rid of the extra HTML that jQuery UI autocomplete creates. React calls componentWillUnmount before removing a component from the page. As in componentDidMount, we can take care of any extra tasks that React is not aware of. In this case, since React did not create the extra HTML for jQuery UI autocomplete, it cannot remove it either.

An extra touch of polish

We can configure the item list for the autocomplete through props. This way, the autocomplete component does not need to know where the list is coming from. You can make an AJAX call in another part of the application and pass the result to the component.

Again, though, we have the problem that React is not aware of the existence of the autocomplete, so changes cannot propagate from the props automatically. To update the autocomplete list with the new props value, we need componentDidUpdate. React calls this function when it is done updating the markup for the component after the props have changed. Inside componentDidUpdate, we then take care to update the autocomplete with the new tag values.

componentDidMount: function() {
  this.updateAutocomplete();
},

componentDidUpdate: function() {
  this.updateAutocomplete();
},

updateAutocomplete: function() {
  var tags = this.props.tags;
  $(React.findDOMNode(this)).autocomplete({source: tags});
}

We can use a further trick to improve performance. We can skip re-rendering if the new tags are the same as the old.

shouldComponentUpdate: function(nextProps) {
  return this.props.tags !== nextpProps.tags;
}

This only works if we never update the tags array in place and always replace it with a new array. To ensure that you would need some immutable data structures