title: How do I set state of sibling components easily in React?
body: <p>I have got the beginnings of a clickable list component that will serve to drive a select element. As you can see from the below, <code>onClick</code> of the <code>ListItem</code>, I'm passing the state of a child element (<code>ListItem</code> in this case) to the parents (<code>SelectableList</code>, and <code>CustomSelect</code> component). This is working fine. However, what I would also like to do is change the state of the <em>sibling</em> components (the other ListItems) so that I can toggle their selected states when one of the ListItems is clicked. </p>
  
  <p>At the moment, I'm simply using <code>document.querySelectorAll('ul.cs-select li)</code> to grab the elements and change the class to selected when it doesn't match the index of the clicked <code>ListItem</code>. This works - to an extent. However, after a few clicks, the state of the component has not been updated by React (only by client side JS), and things start to break down. What I would like to do is change the <code>this.state.isSelected</code> of the sibling list items, and use this state to refresh the SelectableList component. Could anyone offer a better alternative to what I've written below?</p>
  
  <pre><code>var React = require('react');
  var SelectBox = require('./select-box');
  
  var ListItem = React.createClass({
      getInitialState: function() {
          return {
              isSelected: false
          };
      },
  
      toggleSelected: function () {
          if (this.state.isSelected == true) {
              this.setState({
                  isSelected: false
              })
          } else {
              this.setState({
                  isSelected: true
              })
          }
      },
  
      handleClick: function(listItem) {
          this.toggleSelected();
          this.props.onListItemChange(listItem.props.value);
  
          var unboundForEach = Array.prototype.forEach,
              forEach = Function.prototype.call.bind(unboundForEach);
  
          forEach(document.querySelectorAll('ul.cs-select li'), function (el) {
  
              // below is trying to 
              // make sure that when a user clicks on a list
              // item in the SelectableList, then all the *other*
              // list items get class="selected" removed.
              // this works for the first time that you move through the 
              // list clicking the other items, but then, on the second
              // pass through, starts to fail, requiring *two clicks* before the
              // list item is selected again.
              // maybe there's a better more "reactive" method of doing this?
  
              if (el.dataset.index != listItem.props.index &amp;&amp; el.classList.contains('selected') ) {
                  el.classList.remove('selected');
              }
          });
      },
  
      render: function() {
          return (
              &lt;li ref={"listSel"+this.props.key}
                  data-value={this.props.value}
                  data-index={this.props.index}
                  className={this.state.isSelected == true ? 'selected' : '' } 
                  onClick={this.handleClick.bind(null, this)}&gt;
                  {this.props.content}
              &lt;/li&gt;
          );
      }
  });
  
  var SelectableList = React.createClass({
  
      render: function() {
  
          var listItems = this.props.options.map(function(opt, index) {
              return &lt;ListItem key={index} index={index} 
                          value={opt.value} content={opt.label}
                          onListItemChange={this.props.onListItemChange.bind(null, index)} /&gt;;
          }, this);
  
          return &lt;ul className="cs-select"&gt;{ listItems }&lt;/ul&gt;;
      }
  
  })
  
  var CustomSelect = React.createClass({
  
      getInitialState: function () {
          return {
              selectedOption: ''
          }
      },
  
      handleListItemChange: function(listIndex, listItem) {
          this.setState({
              selectedOption: listItem.props.value
          })
      },
  
      render: function () {
  
          var options = [{value:"One", label: "One"},{value:"Two", label: "Two"},{value:"Three", label: "Three"}];
  
          return (
              &lt;div className="group"&gt;
                  &lt;div className="cs-select"&gt;
                      &lt;SelectableList options={options} 
                          onListItemChange={this.handleListItemChange} /&gt;
                      &lt;SelectBox className="cs-select" 
                          initialValue={this.state.selectedOption} 
                          fieldName="custom-select" options={options}/&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          )
      } 
  })
  
  module.exports = CustomSelect;
  </code></pre>