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

maximum call stack error using setState in render function

我开始学习它,但找不到解决方案 -> 我有一个输入,当值超过 20 个字符时,我希望工具提示显示输入的完整值。我已经全部建成并且可以正常工作。问题是我收到最大调用堆栈错误,因为每次按键时状态都会发生变化 - 我不确定 best/correct 的处理方式...任何帮助将不胜感激

查看下面我的代码和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')
)

Why maximum call stack error when using setState in render function ?

因为当我们setStateReact触发组件的重新渲染,如果你在setstate内部渲染然后在setState之后,组件将渲染再次,再次它会发现 setState 再次渲染,它将成为一个无限循环,所以永远不要在 render 方法中做任何 setState

查看 了解有关 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}
/>

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

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

此外,由于您在 render() 中使用了 setState,您会收到一个错误,因为 setState 会触发重新渲染,因此一旦您 if-condition 变为真。

CODEPEN