简体   繁体   English

将函数作为道具发送给它时,React 组件会重新渲染

[英]React component rerenders when sending function as props to it

I have a child component StartExam where I am sending two functions as props, from the parent component.我有一个子组件StartExam ,我从父组件发送两个函数作为道具。 I saw that it keeps rerendering because it gets new values of functions the whole time.我看到它不断重新渲染,因为它一直在获取新的函数值。 I have used this piece of code to find out which props are being updated, and it gave me the two functions that I am sending.我已经使用这段代码找出正在更新哪些道具,它给了我发送的两个函数。

componentDidUpdate(prevProps, prevState, snapshot) {
    Object.entries(this.props).forEach(([key, val]) =>
      prevProps[key] !== val && console.log(`Prop '${key}' changed`)
    );
    if (this.state) {
      Object.entries(this.state).forEach(([key, val]) =>
        prevState[key] !== val && console.log(`State '${key}' changed`)
      );
    }
  }

This is how I am sending functions from the parent component:这就是我从父组件发送函数的方式:

         <Route path={`${matchedPath}/start`}
                 render={
                   this.examStatusGuard(
                     'NOT_STARTED',
                     (props) =>
                       <StartExam 
                         language={this.state.language} 
                         startExam={() => this.startExam()}
                         logAction={(action) => this.logAction({action})}/>)
                 }
          />

and this is the examStatusGuard function:这是examStatusGuard函数:

  examStatusGuard(requiredState, renderFunc) {
    return (props) => {
      if (this.state.exam.status !== requiredState) {
        return <Redirect to={this.examStatusDefaultUrl()}/>
      }
      return renderFunc(props);
    }
  }

And this are the two functions I am sending down as props:这是我作为道具发送的两个函数:

logAction(actionModel) {
    const wholeActionModel = {
      language: this.state.language,
      taskId: null,
      answerId: null,
      ...actionModel
    };
    console.log(wholeActionModel);
    return wholeActionModel;
  }

startExam() {
    this.logAction({action: actions.EXAM_STARTET});

    this.examGateway.startExam()
      .then(() => this.loadExam())
      .then(() => {
        this.props.history.push("/exam/task/0");
        this.logAction({action: actions.TASK_OPEN, taskId: this.state.exam.tasks[0].id});
      });
  };

The reason I don't want the functions to be recreated is that in the child component I have a method that calls logAction , and it is being called the whole time, instead of just once.我不希望重新创建这些函数的原因是在子组件中我有一个调用logAction的方法,并且它一直被调用,而不仅仅是一次。 This is the method:这是方法:

renderFirstPage() { 
  this.props.logAction(actions.INFOSIDE_OPEN); 
  return <FirstPage examInfo={this.props.eksamensInfo}> 
           {this.gotoNextPageComponent()} 
         </FirstPage> 
} 

I have tried with sending the functions like it is suggested in the answer, but with binding this to them:我试图与发送功能,如它在答复建议,但结合this对他们说:

  <StartExam 
      language={this.state.language} 
      startExam={this.startExam.bind(this)}
      logAction={this.logAction.bind(this)}/> 

But, the functions were being recreated again the whole time.但是,这些功能一直在重新创建。 How can I fix this?我怎样才能解决这个问题?

When you send a function like you are, you are creating an anonymous function that is re-created each time the parent component renders:当您像这样发送函数时,您正在创建一个匿名函数,每次父组件渲染时都会重新创建该函数:

startExam={() => this.startExam()}

That's an anonymous function, whose whole purpose in life is to call the actual function startExam .这是一个匿名函数,它在生活中的全部目的是调用实际的函数startExam It's being defined right here in the render function of the parent, so it's re-created each time.它是在父级的渲染函数中定义的,因此每次都会重新创建。 You can alternatively just send that function down itself, ie您也可以直接发送该功能,即

startExam={this.startExam}

In this case the prop now references a stable function that is not getting recreated every time.在这种情况下,道具现在引用一个稳定的函数,不会每次都重新创建。 I imagine that will fix your problem.我想这会解决你的问题。

However, it's not entirely clear to me why it matters that the function is being recreated every time and your child component is re-rendering.但是,我并不完全清楚为什么每次都重新创建该函数并且您的子组件正在重新渲染很重要。 The props aren't changing an infinite amount of time, but rather only when the parent is rerendering.道具不会在无限长的时间内改变,而只会在父级重新渲染时改变。 That's usually not a problem, unless you are basing some other action to see if the previous props have changed (like with lodash, _.isEqual(prevProps,this.props) ).这通常不是问题,除非您基于其他一些操作来查看之前的 props 是否已更改(例如 lodash, _.isEqual(prevProps,this.props) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM