Reputation: 163
I am trying to create a custom event in one component and add an event listener in another component. The component that is listening for the event contains a function that I want to execute on the event. Below are what I have in the two components, I just feel like I'm going about this in the wrong way...
Component #1
toggleWidget() {
const event = new CustomEvent('sliderClicked', {
bubbles: true,
});
const sliderToggle = document.getElementById('input');
sliderToggle.dispatchEvent(event);
this.setState({
checked: !this.state.checked,
});
}
/* and then in my render... */
render() {
const displaySlider = this.state.isSliderDisplayed ? (
<div className="slider-container" >
<label className="switch" htmlFor="input">
<input type="checkbox" checked={this.state.checked} onChange={this.toggleWidget} id="input" />
<span className="slider round" />
</label>
<p className="batch-slider-title"> Batch Widget </p>
</div>) : null;`
Component Two
window.addEventListener('sliderClicked', this.refreshLayout);`
Any ideas as to what I may be doing wrong?
Upvotes: 1
Views: 1385
Reputation: 396
Refs are generally considered something to avoid in React as they couple components together. see the documentation here: https://facebook.github.io/react/docs/refs-and-the-dom.html
Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. See the Lifting State Up guide for examples of this.
Try using a global state container like redux and when you "toggleWidget" in one component, set a property in your redux store. Listen to that property by setting it as a prop in your second component(the one that you want to respond to a change/toggle). On change of that property your component will have the "componentWillReceiveProps" lifecycle method called and you can then have your "responding" component take whatever action you like.
Upvotes: 0
Reputation: 5000
In React it's pretty common to pass down callbacks from parent to child.
const Child = ({handleClick}) => (
<div onClick={ handleClick } >Click me!</div>
);
const Parent = () => {
const childClickHandler = event => {
// do stuff
alert('My child is calling?');
}
return (
<Child handleClick={ childClickHandler }/>
);
};
Maybe that could work for you? You can try the code here. (JSFiddle)
Upvotes: 0
Reputation: 62556
Basically it should work, but in react
- if you rendered an element in a component you can use the ref
to access it:
<input
type="checkbox"
checked={this.state.checked}
onChange={this.toggleWidget}
id="input"
ref={(c) => this.input = c}
/>
And your toggleWidget function should be something like this:
toggleWidget() {
...
this.input.dispatchEvent(event);
...
}
Upvotes: 3