Skip to content Skip to sidebar Skip to footer

Modularize And Abstract React Component Functionality

I have below a working component that allows for a checkbox all and checkboxes. It works perfectly. However I hate the idea that I'm stuck carrying all of this code around every ti

Solution 1:

The following example is in the right general direction I think, the general idea is to introduce a wrapper component for the related boxes, and then walk through the children in that component to tie them together.

varCheckAll = React.createClass({
render() {
  return<inputtype="checkbox" {...this.props} />
}
});
varCheckbox = React.createClass({
render() {
  return<inputtype="checkbox" {...this.props} />
}
});
varCheckboxGroup = React.createClass({
setAll(to) {
  var result = {};
  Object.keys(this.props.boxes).forEach(k => result[k] = to)
  this.props.onChange(result);
},
setOne(name, to) {
  var result = {};
  Object.keys(this.props.boxes).forEach(k => result[k] = this.props.boxes[k])
  result[name] = to;
  this.props.onChange(result);
},
enrichChild(child) {
  var boxes = this.props.boxes;
  var all = Object.keys(boxes).every(k => boxes[k]);
  if (child.type == CheckAll) {
    returnReact.cloneElement(child, { checked: all,
      onChange: () =>this.setAll(!all)
    });
  } elseif (child.type == Checkbox) {
    var name = child.props.name;
    returnReact.cloneElement(child, { checked: !!boxes[name],
      onChange: ({target}) =>this.setOne(name, target.checked)
    });
  } else {
    return child;
  }
},
render() {
  return (
    <div>
      {React.Children.map(this.props.children, this.enrichChild)}
    </div>
  )
}
});


varTest = React.createClass({
  getInitialState: function () {
    return {
      boxes: {
        a: true,
        b: false,
        c: false,
      }
    }
  },
  render: function () {
    return (
    <div><CheckboxGroupboxes={this.state.boxes}onChange={boxes => this.setState({boxes})}
      >
        <CheckAll /><Checkboxname="a" /><Checkboxname="b" /><Checkboxname="c" /></CheckboxGroup></div>
    )
  }
})

React.render(<Test/>, document.body)

Here's a jsbin - https://jsbin.com/zomuxolevo/1/edit?js,output

To allow for more flexibility with the children, you'd need to recursively walk them using something like this gist https://gist.github.com/dandelany/1ff06f4fa1f8d6f89c5e

var RecursiveChildComponent = React.createClass({
  render() {
    return <div>
      {this.recursiveCloneChildren(this.props.children)}
    </div>
  },
  recursiveCloneChildren(children) {
    return React.Children.map(children, child => {
      if(!_.isObject(child)) return child;
      var childProps = {someNew: "propToAdd"};
      childProps.children = this.recursiveCloneChildren(child.props.children);
      return React.cloneElement(child, childProps);
    })
  }
})

Solution 2:

I hacked this together using some jQuery, and lodash.

Here's the example running.

Note, this example goes into the DOM to get the data needed. None of the state of these checkboxes are stored by the component. As far as I can tell there is no true "React" way to do this. (I am very open to suggestion.)

varCheckbox = React.createClass({
  componentDidMount: function () {
    var component = React.findDOMNode(this)
    var $component = $(component)
    if ($component.attr('id')) {
      var selector = 'input'
      selector += '[data-component=Checkbox]'
      selector += '[for=' + $component.attr('id') + ']'var $forComponents = $(selector)
      $component.on('change', function () {
        var value = $component.prop('checked')
        $forComponents.each(function () {
          $forComponent = $(this)
          $forComponent.prop('checked', value)
        })
      })
      $forComponents.on('change', function () {
        var values = $forComponents.map(function () {
          var $forComponent = $(this)
          var value = $forComponent.prop('checked')
          return value
        })
        var simple = _.chain(values).unique().value()
        if (simple.length === 1 && simple[0] === true) {
          $component.prop('checked', true)
        } else {
          $component.prop('checked', false)
        }
      })
    }
  },
  render: function () {
    return (
    <inputtype='checkbox'data-component='Checkbox'
       {...this.props}/>
    )
  }
})

varTest = React.createClass({
  render: function () {
    return (
    <div>
      Select All: <Checkboxid='alpha'/><br/><CheckboxhtmlFor='alpha'/><br/><CheckboxhtmlFor='alpha'/><br/><CheckboxhtmlFor='alpha'defaultChecked/><br/><CheckboxhtmlFor='alpha'/><br/><CheckboxhtmlFor='alpha'/><br/></div>
    )
  }
})

React.render(<Test/>, document.body)

Post a Comment for "Modularize And Abstract React Component Functionality"