This tutorial explains how to create a simple regex filter in React. It allows the user to enter text, and have the a table of data automatically update based on a keypress. The demo can be found here and the Github is here.

To do this in React, we take advantage of purely React's render cycle, and, as well as, immutable data structures to quickly filter the data and output the results. Since we know that React will render when it's state gets updated, we can perform the following:

  1. Set the data to the state on before it mounts or on componentWillMount as Immutable List.
  2. Filter the based on the letters typed from the input.
  3. Update the state and React will render on it's own.

Here is the entire Table component (with some redundancies removed).

import React from 'react';  
const PureRenderMixin = require('react/addons').addons.PureRenderMixin;  
import Immutable from 'immutable';

export default class Table extends React.Component { 

  constructor() {
    this.state = { 
      data: Immutable.List(),
      filteredData: Immutable.List(),
    };
    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);

  }

  componentWillMount() {
    this.setState({ 
      data: Immutable.fromJS(this.props.data).toList(),
      filteredData: Immutable.fromJS(this.props.data).toList() 
    });
  }

  filterData(event) {
    event.preventDefault();
    const regex = new RegExp(event.target.value, 'i');
    const filtered = this.state.data.filter(function(datum) {
      return (datum.get('title').search(regex) > -1);
    });

    this.setState({
      filteredData: filtered,
    });
  }

  render() {
    const { filteredData } = this.state;
    const prettyRows = filteredData.map(function(datum) {
      return (
        <tr>
          <td>{ datum.get("id") }</td>
          <td>{ datum.get("title") }</td>
        </tr>
      );
    });

    return(
      <div className="Table container">
        <input
          type="text"
          className="form-control"
          onChange={ this.filterData.bind(this) }
          placeholder="Search" />

        <table className="table">
          <thead>
            <th>ID</th>
            <th>Title</th>
          </thead>

          <tbody>
            { prettyRows }
          </tbody>
       </table>
     </div>);
   }

I will now breakdown the component, and explain the interesting parts.

The first thing the component is initialize it's states in constructor() and create empty List objects for data and filteredData. The data object is for the original data whereas the filteredData will be the dataset the being searched and edited. We immediately overwrite these state values as the component is mounting in componentWillMount. The data prop is simply the response of a GET request from a lorem ipsum JSON creator. It immediately is converted into an immutable object called a List.

We now have the data in its immutable form and as state object. Skipping over filterData(), we hit the render() method. The method simply takes the filteredData (that is currently the same as data), organizes them in table rows, and then returns the whole table and input form.

Next, we handle the actual searching of data and tell React what to actually do when a user begins typing. We first set an onChange event listener to the input field to handle the keypresses. In this case, we set to the filterData function and bind this to the function so that we have access to the state.

Lastly, we handle the filterData function. This function simply takes the current value of the input form and created a new RegExp that will match case insenitive patterns (given by the i parameter). We then search through the original data object and return the items that having matching patterns in title. This returned immutable List is then just set to the filteredData state. This update will then cause React to render again, displaying the searched data!

In conclusion, making a fast and search-able table was actually really simple to do in React. While there could definitely be some better search guidelines instead of a simple pattern, all the code is isolated in filterData, and improving that wouldn't affect how any other pieces of the search are handled.

Please check out the demo and the code at github. Or email me if you have any questions.

Thanks to @winkler1 for suggesting to use the PureRenderMixin.