简体   繁体   中英

this.forceUpdate() not re-rendering dynamically created components

Assume all the various components have been defined.

In my react component, I want the button click to trigger the appending of a new TextBox component in my dynamically created questions component. When I tested the button click with forceUpdate() , a TextBox was successfully appended to questions but there was no apparent addition of a new TextBox element. I tested whether the component was actually re-rendering by using <h4>Random number : {Math.random()}</h4> and it turns out the component was doing so, as the number changed every time I pressed the button.

Is something being done wrong?

constructor (props) {
  super(props);
  this.questions = [];
  this.questions.push(<TextBox key={this.questions.length}/>);
  this.createTextBox = this.createTextBox.bind(this);
  this.loadTextBox = this.loadTextBox.bind(this);
}

createTextBox() {
  this.questions.push(<TextBox key={this.questions.length}/>);
  this.forceUpdate();
}

loadTextBox() {
  return (this.questions);
}

render() {
  return(
    <div>
      <h4>Random number : {Math.random()}</h4>
      {this.loadTextBox()}
      <ButtonToolbar className="add-question">
        <DropdownButton bsSize="large" title="Add" id="dropdown-size-large" dropup pullRight>
          <MenuItem eventKey="1" onClick={this.createTextBox}>Text Box</MenuItem>
        </DropdownButton>
      </ButtonToolbar>
    </div>
  );
}

Only items inside this.state are properly monitored by React on whether or not a rerender should occur. Using this.forceUpdate does not check to see if this.questions has been changed.

Use this.questions as this.state.questions . When you do this, do not mutate this.state.questions . Instead, make a new copy of it and use this.setState on it.

constructor (props) {
  super(props);
  this.state = {
    questions: [<TextBox key={0}/>]
  }
  this.createTextBox = this.createTextBox.bind(this);
  this.loadTextBox = this.loadTextBox.bind(this);
}

createTextBox() {
  const newQuestions = [...this.state.questions, <TextBox key={this.questions.length}/>]
  // or you can use 
  // const newQuestions = this.state.questions.concat(<TextBox key={this.questions.length + 1}/>)
  this.setState({questions: newQuestions})
}

loadTextBox() {
  return (this.state.questions);
}

One important thing to note is that this.forceUpdate is almost never needed. If you find yourself using it, you are writing your code in an unoptimal way. I made some modifications to your code regarding how keys are assigned. The only reason you should ever be checking for updates is if something in this.state has changed, which involves using this.setState .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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