简体   繁体   中英

ReactJS - Call a component function from outside for multiple instances

I want to call a method exposed by a React component from the outside of React for multiple instances. In bellow exmaple, I wanted to fire the respective toggleOverlay method when the user clicks on anywhere of article DIV. The main DIV is not rendered through React, it was rendered from server-side (AEM) and I can add vanilla javascript into article div to attached the click event.

The configData for each component is different which comes thourgh AEM (server sides).

Example:

<div class="main">
    <div class="article">
        <h3>Lorem Ipsum</h3>
        <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
        <articleOverlay configData="" /> 
    </div>
    <div class="article">
        <h3>Lorem Ipsum</h3>
        <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
        <articleOverlay configData="" />
    </div>
    <div class="article">
        <h3>Lorem Ipsum</h3>
        <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
        <articleOverlay configData="" />
    </div>
</div>


// articleOverlay component
class articleOverlay extends React.Component {
    constructor(props) {
        super(props);
    
        this.state = {
            showOverlay: false
        };

        window.articleOverlay = this;

       toggleOverlay = (e) => {
           if (this.state.showFlyout) {
               this.setState({ showOverlay: true }
           }else{
               this.setState({ showOverlay: false }
           }
       }

    }

    render() {
        const { configData } = this.props;
        return (
            <div className="article-overlay">
                <button className="article-overlay__button" onClick={this.toggleOverlay}>View flows</button>
                {
                    this.state.showOverlay && 
                    <div className="article-overlay__body">
                        <div className="article-overlay__item">
                            {configData.name}
                        </div>
                    </div>
                }
            </div>
        );
    }

}

I had tried to expose the method on window object using - window.articleOverlay = this; and

Calling using -

document.querySelector('.article').addEventListener('click', function(){
  window.articleOverlay.toggleOverlay();
});

But suspecting it should not work for multiple instances, answer from here https://stackoverflow.com/a/50466217/2479903

Is there a way to achieve this?

There's no need to make the function global, just add the event listener to the element in a componentDidMount , and there won't be any issues with multiple listeners that way either.

And since you have multiple articles, don't use querySelector . If the .article isn't part of React, but a parent of the root node, it looks like the best thing to do is attach a ref to a rendered element, then use .closest on it to find the article.

Change

<div className="article-overlay">

to

<div className="article-overlay" ref={div => this.article = div.closest('.article') }>

and use

componentDidMount() {
  this.article.addEventListener('click', this.articleOverlay);
}
// cleanup too...
componentWillUnmount() {
  this.article.removeEventListener('click', this.articleOverlay);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM