0
var React = require('react');
var {Col} = require('react-bootstrap/lib');

var Segment = require('../util/segment-data');

module.exports = React.createClass({
    displayName: 'MyFilter',
    propTypes: {
        children: React.PropTypes.node,
        component: React.PropTypes.string
    },
    render(){
        return (
            this.props.children
        );
    },
    captureEventHandler(){
        var data = {
            label: e.target.innerText ? e.target.innerText : e.target.textContent
        };
        Segment.track(this.props.component, data);
    }
});

Then

<SegmentFilter component={Events.sailing_schedules}>
                        <div onClick={this.handleSort.bind(null, 'departure_date')}>Departure Date <span className='caret'></span></div>
                    </SegmentFilter>

My question is that how do I capture click, enter or any event happening in children in the component SegmentFilter? Is it possible to not specify any DOM element inside render ? So basically I am asking how can I do it without doing the following.

return (
        <div onClick={this.handleClick}>
            {this.props.children}
        </div>
    );
handleClick(e){
    var data = {
        label: e.target.innerText ? e.target.innerText : e.target.textContent
    };
    Segment.track(this.props.component, data);
}

The reason I am avoiding this is because I don't want to specify any html of my wrapper component. Or at worst even if I use the div how can I capture any event of child element inside parent component.

So I am looking to write a global event handler in Segment wrapper which will be called no matter which event fires and not only click in child elements. Let's say it should bubble upto that function handleClick

UPDATE - I referred this but couldn't find my case.

Example for Bubbling and Capturing in React.js

HalfWebDev
  • 7,022
  • 12
  • 65
  • 103

2 Answers2

0

The reason I am avoiding this is because I don't want to specify any html of my wrapper component.

You can use the render callback pattern for this. You specify an event callback for the child. Here is an example of this pattern.

const Child = ({onClick, children}) => (
  <div className="child">
    <button onClick={onClick}>Click</button>
    <div>value is: {children}</div>
  </div>
);

class Parent extends React.Component {
  constructor(props){
    super(props);
    this.state = {};
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(event){
    this.setState({value: new Date().toString()});
  }
  render(){
    return this.props.children({onClick: this.handleClick, value: this.state.value});
  }
}

You use the components like this.

<Parent>
  {({onClick, value}) => <Child onClick={onClick}>{value}</Child>}
</Parent>

Only the child markup will be rendered.

Kunukn
  • 2,136
  • 16
  • 16
0

You can do this my applying onClick prop to all children.

render() {
  return React.Children.map(this.props.children, child => {
    return React.cloneElement(child, {
      onClick: this.captureEventHandler
    });
  });
}
emil
  • 6,074
  • 4
  • 30
  • 38
  • What about firing captureEventHandler when keyboard or some other event happens? Let's say to handle onChange too to be simple. or maybe when enter is pressed for any submit handler. – HalfWebDev Dec 07 '17 at 12:28
  • Now this may work for me by checking `child.props.onClick` or `child.props.onChange` and then attach event accordingly. Only thing is that it throws an error `A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object` in React 0.14 – HalfWebDev Dec 07 '17 at 13:11
  • React 0.14.3 to be specific – HalfWebDev Dec 07 '17 at 13:24
  • This will throw an error in any version as array is returned to render – HalfWebDev Dec 07 '17 at 14:11