渲染函数中使用setState的最大调用堆栈错误

时间:2017-04-23 16:39:18

标签: reactjs setstate

我开始学习它但无法找到解决方案 - >我有一个输入,当值超过20个字符时,我希望工具提示显示为键入的完整值。我把它全部建成并且有点工作。问题是我得到一个最大的调用堆栈错误,因为每次按键都会改变状态 - 我不确定最好/正确的方法...任何帮助将不胜感激

请参阅下面的代码和here is the pen

console.clear();

class Input extends React.Component {

  render(){
    return(
      <div>
        <input
          className="main-input"
          onChange={this.props.onChange}
          placeholder={"Tell me something"}
          />
       </div>
    )
  };

}

class Tooltip extends React.Component {

  render(){
    return(
      <div
        className="tooltip"
        data-status={this.props.isShowing}>
        <p>{this.props.TooltipValue}</p>
      </div>
    )
  }
}

class App extends React.Component {
  constructor(){
    super();
    this.state = {
      message: '',
      isShowing: false
    }
  }

  onChange(e) {
      this.setState({
        message: e.target.value
      });
    }

  render(){
    const inputVal = (this.state.message.length);
    if(inputVal >= 20){
      this.setState({isShowing: true})
    } 
    // else {
    //   this.setState({isShowing: false})
    // }

    return(
      <div className="container">
        <Tooltip
          TooltipValue={this.state.message}
          isShowing={this.state.isShowing}
        />
        <Input onChange={this.onChange.bind(this)}/>
      </div>
    )
  }

}


ReactDOM.render(
  <App />,
  document.getElementById('Main')
)

2 个答案:

答案 0 :(得分:3)

不需要为tooltip使用单独的状态,因为它已经取决于您可以像这样做的状态值

<Tooltip
      TooltipValue={this.state.message}
      isShowing={this.state.message.length > 20}  >     

此外,由于您在setState中使用render(),因此setState会触发重新渲染,从而在if-condition pacman -Sy cordova时启动一个小型循环变成了现实。

<强> CODEPEN

答案 1 :(得分:2)

  

为什么在setState函数中使用render时出现最大调用堆栈错误?

因为当我们执行setState时,React会触发重新呈现组件,如果您在内部渲染中setstate,那么在setState之后,组件将再次渲染,再一次,它会再次找到setState渲染,它将成为一个无限循环,所以永远不要在渲染方法中做任何setState

检查this answer,了解有关setState行为的详细信息。

不要将该检查放在render方法中,而是将其放在onChange方法中,如下所示:

onChange(e) {
    const inputVal = e.target.value;
    this.setState({
        message: inputVal,
        isShowing : inputVal.length > 20 ? true : false
    });
}

删除这些行:

if(inputVal >= 20){
    this.setState({isShowing: true})
} 
// else {
//   this.setState({isShowing: false})
// }

或者由于Tooltip的显示取决于input元素的值,您可以避免额外的变量,并使用Tooltip属性isShowing直接检查输入元素的长度,像这样:

<Tooltip
    TooltipValue={this.state.message}
    isShowing={this.state.message.length >= 20}
/>