React: Cant call a function inside child component

2019-06-19 18:56发布

I am trying to call a function inside child component through this.refs but i keep getting error that this function doesn't exist.

Uncaught TypeError: this.refs.todayKpi.loadTodaysKpi is not a function

Parent component:

class KpisHeader extends React.Component {

  constructor() {
    super();
    this.onUpdate = this.onUpdate.bind(this);
  }
    render(){
        return <div>
            <DateRange ref="dateRange" onUpdate={this.onUpdate}/>
            <TodayKpi ref="todayKpi" {...this.state}/>
          </div>;
    }

  onUpdate(val){

      this.setState({
          startDate: val.startDate,
          endDate: val.endDate
      }, function(){
        this.refs.todayKpi.loadTodaysKpi();
      });
  } 
 }

I want to get some data from DateRange component through function onUpdate, and then I want to trigger a function inside TodayKpi which fetches data from the server. For now it is just console.log("AAA");.

Child component:

class TodayKpi extends React.Component {
    constructor() {
        super();
        this.loadTodaysKpi = this.loadTodaysKpi.bind(this);
    }

    render(){
        console.log(this.props.startDate + " "+ this.props.endDate);
        return <div className="today-kpi">


          </div>;
    }
    loadTodaysKpi(){
        console.log("AAAA");
    }
}

How should I implement this?

2条回答
我想做一个坏孩纸
2楼-- · 2019-06-19 19:19

For reasons I don’t yet grasp, React discourages calling child methods from the parent. However, they relent and give us an ‘escape hatch’ which allows just that. You were correct in thinking that ‘Refs’ were a part of that escape hatch. If, like me, you have read dozens of articles searching for this information, you will be well prepared to understand their description of the escape hatch

In your case, you may want to try something like this in your KpisHeader class.

Change this line

<TodayKpi ref="todayKpi" {...this.state}/>

to use a ref callback function something like this:

<TodayKpi ref={(todayKpiComponent) => this.todayKpiComponent = todayKpiComponent} {...this.state}/>

or, pre-ES6, this:

<TodayKpi 
    ref= 
    {
        function (todayKpiComponent)
        {
            this.todayKpiComponent = todayKpiComponent      
        }
    }
    {...this.state}
 />

Then you will be able to access your todayKpi component methods from your KpisHeader class like this:

this.todayKpiComponent.someMethod();

Oddly, for me, inside the ref callback function, ‘this’ was the window rather than the parent component. So, I had to add

var self = this;

above the render method and use ‘self’ inside the ref callback function.

In my case I had an unknown number of dynamically generated children components, so I put each one into an array. I cleared the array in componentWillUpdate. It all seems to be working but I have an uneasy feeling especially given React’s distaste for calling children’s methods.

查看更多
Ridiculous、
3楼-- · 2019-06-19 19:34

If you want the function/method to be called inside the child, you should pass it to the child from the parent to start with. The other thing that you need to change is onUpdate to onChange, assuming that you want to track every change to that field. The other alternative is to check when it is onSubmit, but it sounds like you want to have it happen every time the field is updated.

查看更多
登录 后发表回答