简体   繁体   中英

Properly unmounting a react component

Sorry I couldn't come up with a more specific title for this question. When I execute the below snippet I get the following warning:

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 Typewriter component.

However, if the render() in MyComponent is changed to the following, I get no such warning:

render() {
  return (
    <div>
      <h1>
        <Typewriter />
        { this.state.render == 1 && "Render 1" }
        { this.state.render == 2 && "Render 2" }
        { this.state.render == 3 && "Render 3" }
      </h1>
    </div>
  );
}

How do I properly unmount this rendered Typewriter component that itself is performing some mounting and unmounting actions? Thanks!

 class Typewriter extends React.Component { constructor(props) { super(); this.state = { finalText: '' } this.typeWriter = this.typeWriter.bind(this); } typeWriter(text, n) { if (n < (text.length)) { if (n + 1 == (text.length)) { let j = text.substring(0, n+1); this.setState({ finalText: j }); n++; } else { let k = text.substring(0, n+1) + '|'; this.setState({ finalText: k }); n++; } setTimeout( () => { this.typeWriter(text, n) }, 100 ); } } componentDidMount() { this.typeWriter('testing_typewriter', 0); } render() { return ( <div> { this.state.finalText } </div> ); } } class MyComponent extends React.Component { constructor(props) { super(); this.state = { render: 1, update: false }; this.interval = null; } componentDidMount() { this.interval = setTimeout( () => this.rendering(), 1700 ); } componentWillUpdate(nextProps, nextState) { if (this.state.render < 3) { this.interval = setTimeout( () => this.rendering(), 1200 ); } } componentWillUnmount() { clearInterval(this.interval); this.interval = null; } rendering() { if (this.state.render < 3) { if (this.interval) { this.setState({ render: this.state.render + 1 }); } } } render() { return ( <div> <h1> { this.state.render == 1 && "Render 1" } { this.state.render == 2 && <Typewriter /> } { this.state.render == 3 && "Render 3" } </h1> </div> ); } } ReactDOM.render(<MyComponent />, app); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="app"></div> 

I had a similar issue and I solved it by clearing the Timeout/Interval in the componentWillUnmount function

in the typewriter function you need to keep track of this timeout:

setTimeout( () => { this.typeWriter(text, n) }, 100 );

with something like

this._timer = setTimeout( () => { this.typeWriter(text, n) }, 100 );

Then add a lifecycle method:

componentWillUnmount() {
  window.clearTimeout(this._timer);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM