React Form Refactor

by Ivan Melgrati

HTML

<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="root"></div>

Babel + JSX

/**
 * Checkbox implemented as a stateless component. Manages change using Form's handleChange event (passed on Form's render method)
 */
const CheckBox = props => {
  let id = props.id;
  return (
    <div className="checkbox-wrapper">
      <span>checkbox {id}</span>
      <input
        type="checkbox"
        value="1"
        id={id}
        name="checkbox-`{id}`"
        onChange={props.handleChange}></input>
    </div>
  );
};

/**
 * Form Component. Displays any child component but only handles state changes from checkboxes. 
 * Other components must handle their own state or use their own onChange methods.
 * Using this strategy avoids having to cycle all checkboxes to get latest values
 */
class Form extends React.Component {
  // Init state
  constructor(props) {
    super(props);
    this.state = {
      checked: []
    };

    // Bind onChange handler to current instance
    this.handleChange = this.handleChange.bind(this);
  }

  // Checkbox onChange handler. Only manages change from child checkboxes. Other input fields are ignored
  handleChange(event) {
    if (event.target.type === "checkbox") {
      let checkboxes = this.state.checked.slice();
      checkboxes[event.target.id] = !checkboxes[event.target.id];
      this.setState({ checked: checkboxes });
      console.log(checkboxes);
    }
  }

  // Generate list of checked items
  showChecked()
  {
    let tmpChecked = this.state.checked;
    let checkedList = [];
    
    tmpChecked.forEach((element,index) => {
      element && checkedList.push(index);
    });

    return checkedList.join('-');
  }

  // Render method. Adds onChange handler to children to ChecBox components to manage stat from Form.
  render() {
    
    // Quick function to walk through direct children and add onChange handler to ChechBox components
    const children = React.Children.map(this.props.children, child => {
      if (child.type === CheckBox) {
        return React.cloneElement(child, {
          handleChange:...