title: Filtering Todo list in React Js
body: <p>I am new to React (I'm used to working with Angular) and I am currently working on filtering my Todo list app based on a category selection. </p>
  
  <p>I cloned the Todo list app from <a href="http://todomvc.com/examples/react/#/" rel="nofollow">http://todomvc.com/examples/react/#/</a> . I added a 'category' input, which works, but now I am trying to filter by category once the list is shown. </p>
  
  <p>I currently don't have any search function for categories and am looking for some guidance as to where to start. I'll post the code below but here is the link to my repo if you want to clone it: <a href="https://github.com/aenser/todo-react" rel="nofollow">https://github.com/aenser/todo-react</a> </p>
  
  <p><em>app.jsx</em></p>
  
  <pre><code>    var app = app || {};
  
  (function () {
      'use strict';
  
      app.ALL_TODOS = 'all';
      app.ACTIVE_TODOS = 'active';
      app.COMPLETED_TODOS = 'completed';
      var TodoFooter = app.TodoFooter;
      var TodoItem = app.TodoItem;
  
      var ENTER_KEY = 13;
  
      var TodoApp = React.createClass({
          getInitialState: function () {
              return {
                  nowShowing: app.ALL_TODOS,
                  editing: null,
                  newTodo: '',
                  newCategory: ''
              };
          },
  
          componentDidMount: function () {
              var setState = this.setState;
              var router = Router({
                  '/': setState.bind(this, {nowShowing: app.ALL_TODOS}),
                  '/active': setState.bind(this, {nowShowing: app.ACTIVE_TODOS}),
                  '/completed': setState.bind(this, {nowShowing: app.COMPLETED_TODOS})
              });
              router.init('/');
          },
  
          handleChange: function (event) {
              this.setState({newTodo: event.target.value});
          },
  
          handleCategoryChange: function (event) {
              this.setState({newCategory: event.target.value});
          },
  
          handleNewTodoKeyDown: function (event) {
              if (event.keyCode !== ENTER_KEY) {
                  return;
              }
  
              event.preventDefault();
  
              var val = this.state.newTodo.trim();
              var cat = this.state.newCategory.trim();
  
              if (val, cat) {
                  this.props.model.addTodo(val, cat);
                  this.setState({newTodo: '', newCategory: ''});
              }
          },
  
          toggleAll: function (event) {
              var checked = event.target.checked;
              this.props.model.toggleAll(checked);
          },
  
          toggle: function (todoToToggle) {
              this.props.model.toggle(todoToToggle);
          },
  
          destroy: function (todo) {
              this.props.model.destroy(todo);
          },
  
          edit: function (todo) {
              this.setState({editing: todo.id});
          },
  
          save: function (todoToSave, text, cat) {
              this.props.model.save(todoToSave, text, cat);
              this.setState({editing: null});
          },
  
          cancel: function () {
              this.setState({editing: null});
          },
  
          clearCompleted: function () {
              this.props.model.clearCompleted();
          },
  
          render: function () {
              var footer;
              var main;
              var todos = this.props.model.todos;
  
              var shownTodos = todos.filter(function (todo) {
                  switch (this.state.nowShowing) {
                  case app.ACTIVE_TODOS:
                      return !todo.completed;
                  case app.COMPLETED_TODOS:
                      return todo.completed;
                  default:
                      return true;
                  }
              }, this);
  
              var todoItems = shownTodos.map(function (todo) {
                  return (
                      &lt;TodoItem
                          key={todo.id}
                          todo={todo}
                          onToggle={this.toggle.bind(this, todo)}
                          onDestroy={this.destroy.bind(this, todo)}
                          onEdit={this.edit.bind(this, todo)}
                          editing={this.state.editing === todo.id}
                          onSave={this.save.bind(this, todo)}
                          onCancel={this.cancel}
                      /&gt;
                  );
              }, this);
  
              var activeTodoCount = todos.reduce(function (accum, todo) {
                  return todo.completed ? accum : accum + 1;
              }, 0);
  
              var completedCount = todos.length - activeTodoCount;
  
              if (activeTodoCount || completedCount) {
                  footer =
                      &lt;TodoFooter
                          count={activeTodoCount}
                          completedCount={completedCount}
                          nowShowing={this.state.nowShowing}
                          onClearCompleted={this.clearCompleted}
                      /&gt;;
              }
  
              if (todos.length) {
                  main = (
                      &lt;section className="main"&gt;
                          &lt;input
                              className="toggle-all"
                              type="checkbox"
                              onChange={this.toggleAll}
                              checked={activeTodoCount === 0}
                          /&gt;
                          &lt;ul className="todo-list"&gt;
                              {todoItems}
                          &lt;/ul&gt;
                      &lt;/section&gt;
                  );
              }
  
              return (
                  &lt;div&gt;
                      &lt;header className="header"&gt;
                          &lt;h1&gt;todos&lt;/h1&gt;
                          &lt;form onKeyDown={this.handleNewTodoKeyDown}&gt;
                              &lt;input
                                  placeholder="What needs to be done?"
                                  value={this.state.newTodo}
                                  autoFocus={true}
                                  className="new-todo"
                                  onChange={this.handleChange}
                              /&gt;
                          &lt;select value={this.state.newCategory} className="new-todo"
                          onChange={this.handleCategoryChange}&gt;
                              &lt;option value=""&gt;Select a Category&lt;/option&gt;
                              &lt;option value="Urgent"&gt;Urgent&lt;/option&gt;
                              &lt;option value="Soon"&gt;Soon&lt;/option&gt;
                              &lt;option value="Anytime"&gt;Anytime&lt;/option&gt;
                          &lt;/select&gt;
  
                          &lt;/form&gt;
                      &lt;/header&gt;
                      {main}
                      {footer}
                  &lt;/div&gt;
              );
          }
      });
  
      var model = new app.TodoModel('react-todos');
  
      function render() {
          React.render(
              &lt;TodoApp model={model}/&gt;,
              document.getElementsByClassName('todoapp')[0]
          );
      }
  
      model.subscribe(render);
      render();
  })();
  </code></pre>
  
  <p><em>todoModel.js</em></p>
  
  <pre><code>var app = app || {};
  
  (function () {
      'use strict';
  
      var Utils = app.Utils;
      // Generic "model" object. You can use whatever
      // framework you want. For this application it
      // may not even be worth separating this logic
      // out, but we do this to demonstrate one way to
      // separate out parts of your application.
      app.TodoModel = function (key) {
          this.key = key;
          this.todos = Utils.store(key);
          this.onChanges = [];
      };
  
      app.TodoModel.prototype.subscribe = function (onChange) {
          this.onChanges.push(onChange);
      };
  
      app.TodoModel.prototype.inform = function () {
          Utils.store(this.key, this.todos);
          this.onChanges.forEach(function (cb) { cb(); });
      };
  
      app.TodoModel.prototype.addTodo = function (title, category) {
          this.todos = this.todos.concat({
              id: Utils.uuid(),
              title: title,
              category: category,
              completed: false
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.toggleAll = function (checked) {
          // Note: it's usually better to use immutable data structures since they're
          // easier to reason about and React works very well with them. That's why
          // we use map() and filter() everywhere instead of mutating the array or
          // todo items themselves.
          this.todos = this.todos.map(function (todo) {
              return Utils.extend({}, todo, {completed: checked});
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.filterAll = function () {
          this.todos = this.todos.map(function (todo) {
              return Utils.extend({}, todo);
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.toggle = function (todoToToggle) {
          this.todos = this.todos.map(function (todo) {
              return todo !== todoToToggle ?
                  todo :
                  Utils.extend({}, todo, {completed: !todo.completed});
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.destroy = function (todo) {
          this.todos = this.todos.filter(function (candidate) {
              return candidate !== todo;
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.save = function (todoToSave, text, cat) {
          this.todos = this.todos.map(function (todo) {
              return todo !== todoToSave ? todo : Utils.extend({}, todo, {title: text}, {category: cat});
          });
  
          this.inform();
      };
  
      app.TodoModel.prototype.clearCompleted = function () {
          this.todos = this.todos.filter(function (todo) {
              return !todo.completed;
          });
  
          this.inform();
      };
  
  })();
  </code></pre>
  
  <p><em>todoItem.jsx</em></p>
  
  <pre><code>var app = app || {};
  
  (function () {
      'use strict';
  
      var ESCAPE_KEY = 27;
      var ENTER_KEY = 13;
  
      app.TodoItem = React.createClass({
          handleSubmit: function (event) {
              var val = this.state.editText.trim();
              var cat = this.state.editCategoryText.trim();
              if (val || cat) {
                  this.props.onSave(val, cat);
                  this.setState({editText: this.props.todo.title, editCategoryText: this.props.todo.category});
              } else {
                  this.props.onDestroy();
              }
          },
  
          handleEdit: function (event) {
              this.props.onEdit();
              this.setState({editText: this.props.todo.title, editCategoryText: this.props.todo.category});
          },
  
          handleKeyDown: function (event) {
              if (event.which === ESCAPE_KEY) {
                  this.setState({editText: this.props.todo.title});
                  this.props.onCancel(event);
              } else if (event.which === ENTER_KEY) {
                  this.handleSubmit(event);
              }
          },
  
          handleChange: function (event) {
              if (this.props.editing) {
                  this.setState({editText: event.target.value});
              }
          },
  
          handleCategoryChange: function (event) {
              if (this.props.editing) {
                  this.setState({editCategoryText: event.target.value});
              }
          },
  
          getInitialState: function () {
              return {editText: this.props.todo.title, editCategoryText: this.props.todo.category};
          },
  
          /**
           * This is a completely optional performance enhancement that you can
           * implement on any React component. If you were to delete this method
           * the app would still work correctly (and still be very performant!), we
           * just use it as an example of how little code it takes to get an order
           * of magnitude performance improvement.
           */
          shouldComponentUpdate: function (nextProps, nextState) {
              return (
                  nextProps.todo !== this.props.todo ||
                  nextProps.editing !== this.props.editing ||
                  nextState.editText !== this.state.editText ||
                  nextState.editCategoryText !== this.state.editCategoryText
              );
          },
  
          /**
           * Safely manipulate the DOM after updating the state when invoking
           * `this.props.onEdit()` in the `handleEdit` method above.
           * For more info refer to notes at https://facebook.github.io/react/docs/component-api.html#setstate
           * and https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate
           */
          componentDidUpdate: function (prevProps) {
              if (!prevProps.editing &amp;&amp; this.props.editing) {
                  var node = React.findDOMNode(this.refs.editField);
                  node.focus();
                  node.setSelectionRange(node.value.length, node.value.length);
              }
          },
  
          render: function () {
              return (
                  &lt;li className={classNames({
                      completed: this.props.todo.completed,
                      editing: this.props.editing
                  })}&gt;
                      &lt;div className="view"&gt;
                          &lt;input
                              className="toggle"
                              type="checkbox"
                              checked={this.props.todo.completed}
                              onChange={this.props.onToggle}
                          /&gt;
                          &lt;label onDoubleClick={this.handleEdit}&gt;
                              {this.props.todo.title}
                          &lt;/label&gt;
                          &lt;label onDoubleClick={this.handleEdit}&gt;
                              {this.props.todo.category}
                          &lt;/label&gt;
                          &lt;button className="destroy" onClick={this.props.onDestroy} /&gt;
                      &lt;/div&gt;
                          &lt;input
                              ref="editField"
                              value={this.state.editText}
                              className="edit"
                              onChange={this.handleChange}
                              onKeyDown={this.handleKeyDown}
                          /&gt;
                          &lt;select value={this.state.EditCategoryText} className="edit" onChange={this.handleCategoryChange} defaultValue={this.props.todo.category} onKeyDown={this.handleKeyDown}&gt;
                              &lt;option value="Urgent"&gt;Urgent&lt;/option&gt;
                              &lt;option value="Soon"&gt;Soon&lt;/option&gt;
                              &lt;option value="Anytime"&gt;Anytime&lt;/option&gt;
                          &lt;/select&gt;
                  &lt;/li&gt;
              );
          }
      });
  })();
  </code></pre>
  
  <p>Thank You for taking the time to help me figure out how to filter my search based on category selection.</p>