简体   繁体   中英

React doesn't render all components of array

I want to dynamically add Components, after clicking the "add" button. For that, I created an array that consists of all the components, and add them on click.

My problem is, that it only renders one component, even though it consists of several ones.

My code looks like this:

class QuestionBlock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {answersArray: []};
    }

    addPossibleAnswer() {
        this.state.answersArray.push(
            <PossibleAnswers id={this.state.answersArray.length + 1}/>
        )
        this.forceUpdate();
    }

    componentWillMount() {
        this.state.answersArray.push(
            <PossibleAnswers id={this.state.answersArray.length + 1}/>
        )
    }

    render() {
        console.log(this.state.answersArray) // Grows after adding componenets, but they are not rendered.
        return (
            <div>
                {this.state.answersArray}
                <AddPossibleAnswer addPossibleAnswer={() => this.addPossibleAnswer()} />
            </div>
        );
    }
}

If you see what I did wrong, I'd be really glad if you could help me out!

You don't interact with state like you do. Never mutate the state field. You need to use this.setState :

this.setState(prevState => ({answersArray: prevState.answersArray.concat([
      <PossibleAnswers id={prevState.answersArray.length + 1}])}));

Having said that, it is also strange that you store components in state. Usually, you would store data and create the components based on the data in the render method.

Instead of mutating state directly and adding JSX to it, you can instead keep raw data in your state and derive the JSX from that in the render method instead.

Example

class QuestionBlock extends React.Component {
  state = { answers: 1 };

  addPossibleAnswer = () => {
    this.setState(({ answers }) => ({ answers: answers + 1 }));
  };

  render() {
    return (
      <div>
        {Array.from({ length: this.state.answers }, (_, index) => (
          <PossibleAnswers key={index} id={index} />
        ))}
        <AddPossibleAnswer addPossibleAnswer={this.addPossibleAnswer} />
      </div>
    );
  }
}

You are directly pushing elements to the array without setState so the component won't re-render

Also avoid using tthis.forceUpdate() as much as you can in your application because this is not recommended much

You need to change your code like below. The recommended approach for dealing with arrays in react is using previous state and push to an array

addPossibleAnswer() {
       this.setState(prevState => ({
          answersArray: [...prevState.answersArray, <PossibleAnswers id={prevState.answersArray.length + 1}/>]
       }));
    }

componentWillMount() {
    this.setState(prevState => ({
          answersArray: [...prevState.answersArray, <PossibleAnswers id={prevState.answersArray.length + 1}/>]
       }));
}

Also keep in mind that componentWillMount life cycle method is deprecated in react 16. So move the code to componentDidMount instead

Here is the corrected code

class QuestionBlock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {answersArray: []};
    }

    addPossibleAnswer() {
       this.setState(prevState => ({
          answersArray: [...prevState.answersArray, <PossibleAnswers id={prevState.answersArray.length + 1}/>]
       }));
    }

  componentDidMount() {
    this.setState(prevState => ({
          answersArray: [...prevState.answersArray, <PossibleAnswers id={prevState.answersArray.length + 1}/>]
       }));
  }

    render() {
        const { answersArray } = this.state;
        return (
            <div>
                {answersArray}
                <AddPossibleAnswer addPossibleAnswer={() => this.addPossibleAnswer()} />
            </div>
        );
    }
}

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