代码之家  ›  专栏  ›  技术社区  ›  zilijonas

无法对未安装的组件调用setState(或forceUpdate)。反应

  •  1
  • zilijonas  · 技术社区  · 6 年前

    古腾塔,伙计们!

    卸载组件后,我不断从应用程序中收到以下错误消息:

    Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
        in Header (at index.js:27)
    

    下面是Header组件的代码:

    class Header extends Component {
      isCancelled = false;
      state = {
        someStateVars: x,
        separateColumns: 'true',
      }
    
      handleChange = (event) => {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;
    
        if (!this.isCancelled) {
          this.setState({ //######THIS IS LINE 27######
            [name]: value
          });
        }
      }
    
      handleDisplayChange = (event) => {
        const value = event.target.value;
        const name = 'separateColumns';
    
        if (!this.isCancelled) {
          this.setState({  
            [name]: value
          }, () => {
            this.props.displayChange();
          });
        }
      }
    
      serversRefresh = () => {
    
        if (!this.isCancelled) {
          setTimeout(() => {
            this.setState({refreshed: false});
          }, localStorage.getItem('seconds')*1000); //disable refresh for 15 seconds
        }
      }
    
      reactivateButton = () => {
        if (!this.isCancelled) this.setState({refreshed: false});
      }
    
      componentDidMount() {
        if(localStorage.getItem('seconds')>5 && !this.isCancelled){
          this.setState({refreshed: true});
        }
      }
    
      componentWillUnmount() {
        this.isCancelled = true;
      }
    }
    

    当我看到得到这个错误时,我已经将componentWillUnmount()函数中更改的isCancelled变量添加到true中。

    我该怎么修?

    在我遇到这个问题的另一个组件上,“isCancelled”var确实有帮助,但在这里我看到它没有影响,问题仍然存在。

    1 回复  |  直到 6 年前
        1
  •  8
  •   Limbo    6 年前

    只需将超时存储在一个变量中,例如。

    this.timeout = setTimeout(/* your actions here*/, /* your timeout */)
    

    然后清除 componentWillUnmount

    componentWillUnmount() {
        clearTimeout(this.timeout)
    }
    

    不用拐杖就能解决你的问题 this.isCancelled . 检测组件的装载状态是不可操作的,因为即使在卸载之后它仍然从内存中卸载。

    setTimeout 返回将来可以取消的计时器id。 clearTimeout 如果超时尚未执行,则按其id取消超时。

    更多关于您的案例,请阅读: Why isMounted is antipattern

    更多关于定时器的信息 MDN .