|
| 1 | +--- |
| 2 | +id: expose-component-functions |
| 3 | +title: Expose Component Functions |
| 4 | +layout: tips |
| 5 | +permalink: expose-component-functions.html |
| 6 | +prev: communicate-between-components.html |
| 7 | +--- |
| 8 | + |
| 9 | +There's another (uncommon) way of [communicating between components](/react/tips/communicate-between-components.html): simply expose a method on the child component for the parent to call. |
| 10 | + |
| 11 | +Say a list of todos, which upon clicking get removed. If there's only one unfinished todo left, animate it: |
| 12 | + |
| 13 | +```js |
| 14 | +/** @jsx React.DOM */ |
| 15 | + |
| 16 | +var Todo = React.createClass({ |
| 17 | + render: function() { |
| 18 | + return <div onClick={this.props.onClick}>{this.props.title}</div>; |
| 19 | + }, |
| 20 | + |
| 21 | + //this component will be accessed by the parent through the `ref` attribute |
| 22 | + animate: function() { |
| 23 | + console.log('Pretend %s is animating', this.props.title); |
| 24 | + } |
| 25 | +}); |
| 26 | + |
| 27 | +var Todos = React.createClass({ |
| 28 | + getInitialState: function() { |
| 29 | + return {items: ['Apple', 'Banana', 'Cranberry']}; |
| 30 | + }, |
| 31 | + |
| 32 | + handleClick: function(i) { |
| 33 | + var items = this.state.items; |
| 34 | + items.splice(i, 1); |
| 35 | + this.setState({items: items}, function() { |
| 36 | + if (items.length === 1) { |
| 37 | + this.refs.item0.animate(); |
| 38 | + } |
| 39 | + }.bind(this)); |
| 40 | + }, |
| 41 | + |
| 42 | + render: function() { |
| 43 | + return ( |
| 44 | + <div> |
| 45 | + {this.state.items.map(function(item, i) { |
| 46 | + var boundClick = this.handleClick.bind(this, i); |
| 47 | + return ( |
| 48 | + <Todo onClick={boundClick} key={i} title={item} ref={'item' + i} /> |
| 49 | + ); |
| 50 | + }, this)} |
| 51 | + </div> |
| 52 | + ); |
| 53 | + } |
| 54 | +}); |
| 55 | + |
| 56 | +React.renderComponent(<Todos />, mountNode); |
| 57 | +``` |
| 58 | + |
| 59 | +Alternatively, you could have achieve this by passing the `todo` an `isLastUnfinishedItem` prop, let it check this prop in `componentDidUpdate`, then animate itself; however, this quickly gets messy if you pass around different props to control animations. |
0 commit comments