2

I'm creating a React component (parent) that receives a link, button, or other React component (child) as a property, and I want to attach an additional click handler to the passed-in component. This child component usually already has a click handler defined, so I can't just add onClick to it using React.cloneElement. Also, sometimes the child component's click handler prevents event propagation to the parent component, so I can't just attach the click listener to the parent and allow the event to bubble up.

Edit: The parent/child relationship and how/where the extra event listener should be attached makes this question slightly different from other questions I've seen, where the answer is to pass a callback (or array of callbacks) into the child component. I do not have access to alter the child component's API.

Here's some sample code:

export default class ParentComponent extends React.Component {
    constructor(props) {
        super();

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(event) {
        // do something (this is not working)
    }

    render() {
        let { childComponent } = this.props;

        return (
            <div>
                {React.cloneElement(childComponent, {
                    onClick: this.handleClick
                })}
            </div>
        )
    }
}

ParentComponent.PropTypes = {
    childComponent: PropTypes.element
};
Jared
  • 1,254
  • 7
  • 19
  • 26
  • 1
    Possible duplicate of [How to add multiple event handlers to same event in React.js](http://stackoverflow.com/questions/33398613/how-to-add-multiple-event-handlers-to-same-event-in-react-js) – djthoms Feb 20 '17 at 21:25
  • 1
    Have you tried [refs](https://facebook.github.io/react/docs/refs-and-the-dom.html) or [findDomNode](https://facebook.github.io/react/docs/react-dom.html#finddomnode) ? – Telman Feb 20 '17 at 21:26
  • Thanks @TelmanAgababov! I'm pretty new to React, and your suggestion worked well. If you want credit, feel free to post a code sample as an answer and I'll accept it. – Jared Feb 27 '17 at 19:21
  • @djthoms, I don't think the StackOverflow question you linked to as a duplicate is exactly the same situation as I have here. If there's another one that matches better, feel free to post it. Thanks! – Jared Feb 27 '17 at 19:25
  • Does this answer your question? [Call multiple functions onClick ReactJS](https://stackoverflow.com/questions/26069238/call-multiple-functions-onclick-reactjs) – Krisztián Balla May 05 '20 at 12:52

1 Answers1

1

The best way I've found to do this so far uses refs and findDOMNode, as suggested in the comments above. Once you have a reference to the child component's DOM node, you can add a regular event listener when the parent component gets mounted:

export default class ParentComponent extends React.Component {
    constructor(props) {
        super(props);
    }

    componentDidMount() {
        this.childComponentRef.addEventListener('click', function() {
            // do something (this works!)
        }, false);
    }

    render() {
        let { childComponent } = this.props;

        return (
            <div>
                {React.cloneElement(childComponent, {
                    ref: (childComponentRef) => {
                        this.childComponentRef = ReactDOM.findDOMNode(childComponentRef);
                    }
                })}
            </div>
        )
    }
}

ParentComponent.PropTypes = {
    childComponent: PropTypes.element
};
Jared
  • 1,254
  • 7
  • 19
  • 26