Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

maximum call stack error using setState in render function

I'm starting to learn it but can't find a solution for this -> I have an input and when the value exceeds 20 characters I want a tooltip to appear with the full value as is typed. I have it all built and kind of working. Problem is that I get a maximum call stack error because the state is being changed on every key press - I'm not sure of the best/correct way to go about it... any help would be greatly appreciated

See my code below and 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')
)
like image 566
ironmike Avatar asked Aug 04 '26 21:08

ironmike


2 Answers

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

Because when we do setState, React trigger the re-rendering of the component, if you do setstate inside render then after setState, component will render again, again it will find setState again render, it will become a infinite loop, So never do any setState inside render method.

Check this answer for more details about setState behaviour.


Instead of putting that check inside render method, put that inside onChange method, like this:

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

And remove these lines:

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

Or since the showing of Tooltip depends on the value of input element, you can avoid extra variable and directly check the length of input element with Tooltip property isShowing, like this:

<Tooltip
    TooltipValue={this.state.message}
    isShowing={this.state.message.length >= 20}
/>
like image 111
Mayank Shukla Avatar answered Aug 06 '26 13:08

Mayank Shukla


No need to use a separate state for the tooltip since it already depends on the state value you can do it like this

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

Also since you are using setState in the render() you are getting an error because setState triggers a re-render and thus beginning an infine loop as soon as you if-condition becomes true.

CODEPEN

like image 23
Shubham Khatri Avatar answered Aug 06 '26 12:08

Shubham Khatri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!