Reputation: 1734
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?
Upvotes: 0
Views: 98
Reputation: 371049
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);
}
Upvotes: 1