【问题标题】:setState Warning in child component. Warning: Can only update a mounted or mounting component子组件中的 setState 警告。警告:只能更新已安装或正在安装的组件
【发布时间】:2017-05-17 09:22:17
【问题描述】:

我有一个显示项目列表的页面,当用户单击该特定项目时,会在 render() 中调用视图组件。

家长:

 constructor(props) {
    super(props);
    this.state = {
      showData : [],
      view : false,
      projectId: ''
    };
    this.buttonHandler = this.buttonHandler.bind(this);
    this.back = this.back.bind(this);
  };


// change view state to true to render diff component
    buttonHandler(){
    this.setState({view:true})
  };



  back(){

    this.setState({view:true})
  }

 render(){

   let compA = (
  <Paper>
        <List>
            <Subheader >New 
            Projects</Subheader>
            {this.state.showData.map(item =>
                <div key={item.title}>
                    <ListItem onClick={()=> 
                   this.buttonHandler()} leftAvatar=
                   {<Avatar icon={<Wallpaper />} />} primaryText=
                   "test" secondaryText="test" />
                    <Divider inset={true} />
                </div>
            )}
        </List>
    </Paper>
);

let compB = (
  <ReviewProject
    back={this.back}/>
);
  return(
      <div>
        {this.state.view?compB:compA}
      </div>
    );
}

儿童补偿 B:

constructor(props) {
 super(props);
this.state = {
//some code
};

}
//calls function back from parent which sets state the "view" to false
 dismiss() {
    this.props.back();
  };

当子进程调用dismiss()函数返回列表组件compA时,会弹出警告:

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the compB component.

有没有办法解决这个问题?以及从一个组件到另一个组件来回导航的好习惯是什么

【问题讨论】:

  • dismiss函数怎么调用,back函数的定义能不能添加
  • 如果你可以使用routes来渲染不同的组件,那就太好了。
  • 我在 compB 调用了解除函数,然后将 compA 中的视图状态设置为 false。我已经重新编辑了
  • 你在后面的函数中分配了true,你应该将它设置为false
  • @Panther,嗯,是的,但是如果我只想让父级的状态根据状态的值呈现组件,这就是我想要实现的。它正在工作,但它向我发出警告

标签: reactjs ecmascript-6


【解决方案1】:

因为实际上在第一次渲染时,如果 compA 被渲染,那么 compB 丢失,因此当 react 尝试重新渲染时,它找不到丢失的元素。

==> 解决方案

render(){                            
    let returnedComp = (
      <Paper>
            <List>
                <Subheader >New Projects</Subheader>
                {this.state.showData.map(item =>
                    <div key={item.title}>
                        <ListItem onClick={()=> 
                       this.buttonHandler()} leftAvatar=
                       {<Avatar icon={<Wallpaper />} />} primaryText=
                       "test" secondaryText="test" />
                        <Divider inset={true} />
                    </div>
                )}
            </List>
        </Paper>
    );

        if (this.state.view) {
            returnedComp = (
              <ReviewProject back={this.back}/>
            );
        }
      return(
          <div>
            {returnedComp}
          </div>
        );
}  

【讨论】:

  • 最初 this.state.view 是 false,这反过来会在第一次渲染时渲染 compA。当 buttonHandler 由 onTouchTap 触发时,它会将视图设置为 true,然后触发重新渲染。 {this.state.view?compB:compA} 是如果 this.state.view 为真则 compB 否则 compA。谢谢,但我认为这不会解决我的警告
  • 你能试试这个吗,或者你已经试过了吗?你的逻辑听起来不错,但问题是反应,jsx 将有自己的规则!上面的答案是从我的真实代码中复制而来的,它修复了我之前几乎相同的问题!
  • 是的,我刚刚尝试过,但仍然收到相同的警告。我相信这与我从未安装的组件调用 setState 有关。无论如何感谢您的建议。
【解决方案2】:

您也可以在设置状态之前尝试使用 ref 如下定义 函数(){

 if (this.refs.ref) 
   this.setState({view: true});
}

render() {
  return (
    <div ref="ref">{this.state.view}</div>
  );
}

【讨论】:

  • 我已经绑定了dismiss。我的 buttonHandler() 也绑定到 onTouchTap,所以当触发它时,它将呈现 compB 而不是我最初声明 state.view 为 false 的 compA。我已经达到了我想要的输出,只是我不断收到警告。谢谢你的建议。
【解决方案3】:

我找到的解决办法是:

创建一个名为viewProject的第三个组件来处理AB之间的切换。

class A extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div>
        This is component A
        <button onClick={this.props.onGoBClick}>Go to B</button>
      </div>
    )
  }
}

class B extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div>
        This is component B
        <button onClick={this.props.onGoAClick}>Go to A</button>
      </div>
    )
  }
}

class ViewContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      view: false,
    }
    this.goToA = this.goToA.bind(this);
    this.goToB = this.goToB.bind(this);
  }

  goToA() {
    this.setState({view: false})
  }

  goToB() {
    this.setState({view: true})
  }

  render() {
    return (
      this.state.view ?
        <B onGoAClick={this.goToA}/>
      :
        <A onGoBClick={this.goToB}/>
    )
  }
}

ReactDOM.render(<ViewContainer />, document.getElementById('app'))

【讨论】:

    猜你喜欢
    • 2017-04-26
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 2019-08-15
    • 1970-01-01
    • 2016-09-25
    • 2018-03-26
    相关资源
    最近更新 更多