I have a custom component Foo
, whose ‘bar
‘ function I want to trigger from the outside:
class Foo extends React.Component { bar() { ... } }
I am rendering Foo
along with a button
whose purpose is to trigger Foo.bar()
:
render() { return ( <Foo ...> </Foo> <Button onClick={I want to trigger Foo.bar()} /> ); }
Things I have tried:
- Moving
<Button >
insideFoo
, then addingonClick
of<Button/>
inFoo's
constructor — the binding of onClick didn’t work — I see it attached, but the<Button />
still does not triggeronClick
. (or, if it can work, how to do it properly)?
Solutions that don’t do what I want:
I see one potential solution which suggests to listen to a click in the entire
MyComponent
, then do some DOM querying to find if the actual button was clicked. This won’t work for me, however, becauseMyComponent
does not own these buttons (these buttons are notMyComponent.props.children
) and I’d prefer to brainstorm a solution that doesn’t force me to have to move the buttons inside.Another potential solution doesn’t work: I cannot have the
render()
return the value of<MyComponent />
into avar myComp
, then inside<Button onClick={() => {myComp.blah()}} />
, because<Button />
itself is instantiated inside<MyComponent />
as a child! (and, they are both in the same render() call anyways)Part b) #2 (above), using React-Component static class method, will not work either: I need this on a per-instance basis.
Using app state (such as a store) is not what I want, either —
MyComponent
is meant to be a re-usaable widget and cannot be tied to a specific application state or listening to any specific stores or store actions.
Any suggestions?
Thanks
Advertisement
Answer
You can define a function on the parent which has a ref to the Foo child. This function will call this.refs.foo.yourFunction(); You then pass that function into the button so when the button is clicked, the parent’s function will be called. Added an example here where clicking the button will toggle the state of the Foo component (but it could do anything).
Example below
class Parent extends React.Component { triggerFoo() { this.foo.toggle(); } render() { return ( <div> <Foo ref={foo => this.foo = foo} /> <Button onClick={this.triggerFoo.bind(this)}/> </div> ); } } class Foo extends React.Component { state = {foo: false} toggle() { this.setState({ foo: !this.state.foo }); } render() { return ( <div> Foo Triggered: {this.state.foo.toString()} </div> ); } } class Button extends React.Component { render() { return ( <button onClick={this.props.onClick}> Click This </button> ); }; } ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root" />