渲染前的设置状态-无法在尚未安装的组件上调用setState

I have the following code: I would like to render out the choice-main-div as many times as the problemcount represents.

class ChoiceTextBubble extends Component{
    constructor(props) {
        super(props);   

        this.state = {
                problemcount:3,
                renderArray:''
            }

        this.renderProblem();               
    }

    onChange(e){
        this.props.updateStoredContent(e);
    }

    renderProblem(){
        var tempArray=[];
        for (var i=0; i<this.state.problemcount;i++){
            tempArray.push(
            <div className="choice-main-div"> 
                <div className="mini-icon"> 
                    <img alt="mini-icon" src={exclam_icon}/>
                </div>
                <div className="choice-div">
                    <form>
                        <input onChange={ e => this.onChange(e)}  autocomplete="off" className ="nice-border normal" type="normal" name="input_problem 01" placeholder={this.props.desc[0]} />
                    </form>
                </div>
            </div>
            )   
            console.log(tempArray);
        }
        this.setState({renderArray: tempArray});
    }

    render() {
        return(
            <div className="textbubble"> 
                <div className="form-section single">
                    <div className="title">
                        <h3>{this.props.title.toUpperCase()}</h3>
                    </div>
                    <div>
                        {this.state.renderArray}
                    </div>
                </div>
            </div>
        )
    }
}
export default ChoiceTextBubble;

但是,我收到以下警告:

Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the ChoiceTextBubble component.

我试图在渲染之前设置renderArray的状态。

评论
  • 萌嘟嘟
    萌嘟嘟 回复

    问题 :

    Because you are calling setState before render, via constructor,

    constructor(props) {
        super(props); 
        this.state = {
                problemcount:3,
                renderArray:''
        }
        this.renderProblem();               
    }
    
    renderProblem(){
        ...
        // Error is due to this line
        this.setState({renderArray: tempArray}); // <----- HERE
    }
    

    解决方案:

    this.renderProblem();

    constructor(props) {
        super(props);   
    
    
        this.problemcount = 3
    
        // you can init state directly from the function's return
        this.state = {
            problemcount : this.problemcount ,
            renderArray: this.renderProblem(this.problemcount)
        }
    }
    
    
    // crate a function that returns the result instead of setting up state
    renderProblem(problemcount){
        var tempArray=[];
        for (var i=0; i<problemcount;i++){
            tempArray.push(
            <div className="choice-main-div"> 
                <div className="mini-icon"> 
                    <img alt="mini-icon" src={exclam_icon}/>
                </div>
                <div className="choice-div">
                    <form>
                        <input onChange={ e => this.onChange(e)}  autocomplete="off" className ="nice-border normal" type="normal" name="input_problem 01" placeholder={this.props.desc[0]} />
                    </form>
                </div>
            </div>
            )   
            console.log(tempArray);
        }
        return tempArray;
    }
    

    您可以检查以下代码段并进行检查,希望这可以消除您的所有疑问

    class App extends React.Component {
      constructor(props) {
          super(props);   
          this.problemcount = 3
          this.state = {
              problemcount: this.problemcount,
              renderArray: this.renderProblem(this.problemcount)
          }
      }
    
      renderProblem(problemcount){
          var tempArray=[];
          for (var i=0; i<problemcount;i++){
              tempArray.push(
              <div className="choice-main-div"> 
                  <div className="mini-icon"> 
                      IMG
                  </div>
                  <div className="choice-div">
                      <form>
                          <input onChange={ e => this.onChange(e)}  autocomplete="off" className ="nice-border normal" type="normal" name="input_problem 01" />
                      </form>
                  </div>
              </div>
              )   
              console.log(tempArray);
          }
          return tempArray;
      }
    
        render() {
            return(
                <div className="textbubble"> 
                    <div className="form-section single">
                        <div className="title">
                            
                        </div>
                        <div>
                            {this.state.renderArray}
                        </div>
                    </div>
                </div>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('react-root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="react-root"></div>
  • l717356465
    l717356465 回复

    您不需要存储要在状态下呈现的数据,您可以直接调用该函数并将结果呈现在render中,如下所示

    class ChoiceTextBubble extends Component{
        constructor(props) {
            super(props);   
    
            this.state = {
                    problemcount:3,
                    renderArray:''
                }
    
        }
    
        onChange(e){
            this.props.updateStoredContent(e);
        }
    
        renderProblem(){
            var tempArray=[];
            for (var i=0; i<this.state.problemcount;i++){
                tempArray.push(
                <div className="choice-main-div"> 
                    <div className="mini-icon"> 
                        <img alt="mini-icon" src={exclam_icon}/>
                    </div>
                    <div className="choice-div">
                        <form>
                            <input onChange={ e => this.onChange(e)}  autocomplete="off" className ="nice-border normal" type="normal" name="input_problem 01" placeholder={this.props.desc[0]} />
                        </form>
                    </div>
                </div>
                )   
                console.log(tempArray);
            }
           return tempArray;
        }
    
        render() {
            return(
                <div className="textbubble"> 
                    <div className="form-section single">
                        <div className="title">
                            <h3>{this.props.title.toUpperCase()}</h3>
                        </div>
                        <div>
                            {this.renderProblem()}
                        </div>
                    </div>
                </div>
            )
        }
    }
    export default ChoiceTextBubble;
    

    附言之所以收到警告,是因为您在调用setState的构造函数中调用了renderProblem函数。