Search code examples
jqueryreactjslodashdom-selection

jQuery-Like Way to Find / Select Array of React Elements


I created this little function to find children of a specific type.

I'd like to be able to select children via property like jQuery, [name="example"]. Is there any way to strip the string selector functionality from jQuery to create an object map to feed to something like lodash's _.find?

I realize this is a fake solution for selecting / finding / filtering an array but I think it can be really useful. I also know that it won't find deep children, it would just deal with direct root children.

Does this exist within react already?

function containsElement (element, children) {
  var result = []
  element = _.flatten([element])
  if (React.isValidElement(children) && !_.isArray(children)) {
    var contains = _.contains(element, children.type)
    if (contains) return children
    return false
  } else if (!React.isValidElement(children) && !_.isArray(children)) {
    return false
  }
  children.forEach(function (child) {
    var isElm = React.isValidElement(child)
    var contains = _.contains(element, child.type)
    if (isElm && contains) {
      result.push(child)
    }
  })
  if (!result.length) return false
  return result
}

Solution

  • Here's a simple version of what I want that only supports element type.

    selectElements('div, span', this.props.children)
    

    Ideally I can do this and it would get all divs with the name prop set to hello.

    selectElements('div[name="hello"]', this.props.children)
    

    Here's full example, (jsbin).

    var selectElements = function (selectorString, reactElements) {
      var selectors = selectorString.split(',')
      selectors = _.map(selectors, function (item) {
        return item.replace(/^\s+|\s$/, '')
      })
      return _.filter(reactElements, function (reactElement) {
        return _.contains(selectors, reactElement.type)
      })
    }
    
    var OnlyElements = React.createClass({
      displayName: 'OnlyElements',
      getInitialState: function () {
        return {
          children: this.props.children
        }
      },
      componentWillMount: function () {
        this.setState({
          children: selectElements(this.props.allow, this.props.children)
        })
      },
      render: function () {
        return (
          <div>
            {this.state.children}
          </div>
        )
      }
    })
    
    var Test = React.createClass({
      displayName: 'Test',
      render: function () {
        return (
          <OnlyElements allow='div'>
            <span>Alpha</span>
            <div>Beta</div>
            <span>Gamma</span>
          </OnlyElements>
        )
      }
    })
    
    React.render(<Test/>, document.body)