1
\$\begingroup\$

I'm trying to break down the individual functionality of a advanced table UI into different react components (right now all table components are really heavy).

I came up with this way of exposing properties of a component to the parent component which allows components to talk to each other. It's quite messy and I'm looking for better ways of achieving this.

Here's the working demo.

function filter (value, caseSensitive, children) {
  return main.recursion (children, function (children, recursion, wrapper) {
    return _.filter(children, wrapper(function (child) {
      if (typeof child.props.children !== 'string') {
        var result = recursion(child.props.children)
        return Boolean(result.length)
      } else {
        var flag = (caseSensitive) ? '' : 'i'
        var pattern = new RegExp(value, flag)
        return (child.props.children.match(pattern))
      }
    }))
  })
}

var FilterChildren = React.createClass({
  displayName: 'FilterChildren',
  propTypes: {
    children: React.PropTypes.node,
    provideFilter: React.PropTypes.func,
    provideFilterChildren: React.PropTypes.func,
    onFilter: React.PropTypes.func,
    caseSensitive: React.PropTypes.bool,
    selector: React.PropTypes.string
  },
  getInitialState: function () {
    return {
      children: this.props.children
    }
  },
  componentWillMount: function () {
    if (this.props.provideFilter) this.props.provideFilter(this.filter)
    if (this.props.provideFilterChildren) this.props.provideFilterChildren(this.filterChildren)

  },
  filterChildren: function (children) {
    this.children = children
  },
  filter: function (value) {
    this.props.onFilter(filter(value, this.props.caseSensitive, this.children))
  },
  render: function () {
    return this.state.children
  }
})

var StatefulChildren = React.createClass({
  displayName: 'StatefulChildren',
  propTypes: {
    children: React.PropTypes.node,
    provide: React.PropTypes.func,
    supply: React.PropTypes.func,
    element: React.PropTypes.string
  },
  getInitialState: function () {
    return {
      children: this.props.children
    }
  },
  componentWillMount: function () {
    if (this.props.provide) this.props.provide(this.setChildren)
    if (this.props.supply) this.props.supply(this.props.children)
  },
  setChildren: function (children) {
    this.setState({
      children: children
    })
  },
  render: function () {
    return React.createElement(
      this.props.element,
      null,
      this.state.children
    )
  }
})

var Page = React.createClass({
  invokeFilter: function (event) {
    return this.filter(event.target.value)
  },
  handleFilter: function (nodes) {
    this.setTbodyChildren(nodes)
  },
  provideFilter: function (filter) {
    this.filter = filter
  },
  provideFilterChildren: function (filterChildren) {
    this.filterChildren = filterChildren
  },
  provideSetTbodyChildren: function (setTbodyChildren) {
    this.setTbodyChildren = setTbodyChildren
  },
  supplyTbodyChildren: function (tbodyChildren) {
    this.filterChildren(tbodyChildren)
  },
  render: function () {
    return (
      <div>
        <input type='text' onChange={this.invokeFilter}></input>
        <table>
          <FilterChildren provideFilter={this.provideFilter} provideFilterChildren={this.provideFilterChildren} onFilter={this.handleFilter}>
            <StatefulChildren element='tbody' provide={this.provideSetTbodyChildren} supply={this.supplyTbodyChildren}>
              <tr>
                <td>French Fries</td>
                <td>Mimes</td>
                <td>Discotech</td>
              </tr>
              <tr>
                <td>Bread</td>
                <td>Coffee</td>
                <td>Wine</td>
              </tr>
            </StatefulChildren>
          </FilterChildren>
        </table>
      </div>
    )
  }
})

React.render(<Page/>, document.body)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.