更好的方法在componentWillUnmount中clearTimeout

Tur*_*ets 12 javascript asynchronous settimeout reactjs react-native

我有一个工作的加载组件,它在加载8秒后取消.这段代码有效,但感觉不对我,我想知道是否有更好的方法来做到这一点.

没有设置this.mounted我得到错误:

警告:只能更新已安装或安装的组件.这通常意味着您在已卸载的组件上调用了setState,replaceState或forceUpdate.这是一个无操作.请检查加载组件的代码.

这让我觉得计时器没有被取消所以继续this.seState.如果我clearTimeout进去,为什么会这样componentWillUnmount?有没有比使用全局更好的方法来解决这个问题this.mounted

class Loading extends Component {
  state = {
    error: false,
  };

  componentDidMount = () => {
    this.mounted = true;
    this.timer();
  };

  componentWillUnmount = () => {
    this.mounted = false;
    clearTimeout(this.timer);
  };

  timer = () =>
    setTimeout(() => {
      (this.mounted && this.setState({ error: true })) || null;
    }, 8000);

  render() {
    const { showHeader = false } = this.props;
    const { error } = this.state;
    return (
      <View style={backgroundStyle}>
        {showHeader && <HeaderShell />}
        {!error &&
          <View style={loadingHeight}>
            <PlatformSpinner size="large" />
          </View>}
        {error && <Error code="service" />}
      </View>
    );
  }
}

Loading.propTypes = {
  showHeader: PropTypes.bool,
};

Loading.defaultProps = {
  showHeader: false,
};

export default Loading;
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 26

这让我觉得计时器没有被取消

正如Pointy所说,事实并非如此.你正在传递一个函数(this.timer)clearTimeout.您需要传递setTimeout 返回值(计时器的句柄),以便您可以使用该句柄取消它.

在这样一个简单的组件中,我没有看到对该timer功能的需要,它只是增加了复杂性; 我只是在CDM中设置了计时器:

class Loading extends Component {
  state = {
    error: false,
  };

  componentDidMount = () => {                // ***
    // Remember the timer handle             // ***
    this.timerHandle = setTimeout(() => {    // ***
      this.setState({ error: true });        // ***
      this.timerHandle = 0;                  // ***
    }, 8000);                                // ***
  };                                         // ***
                                             // ***
  componentWillUnmount = () => {             // ***
    // Is our timer running?                 // ***
    if (this.timerHandle) {                  // ***
        // Yes, clear it                     // ***
        clearTimeout(this.timerHandle);      // ***
        this.timerHandle = 0;                // ***
    }                                        // ***
  };                                         // ***

  render() {
    const { showHeader = false } = this.props;
    const { error } = this.state;
    return (
      <View style={backgroundStyle}>
        {showHeader && <HeaderShell />}
        {!error &&
          <View style={loadingHeight}>
            <PlatformSpinner size="large" />
          </View>}
        {error && <Error code="service" />}
      </View>
    );
  }
}

Loading.propTypes = {
  showHeader: PropTypes.bool,
};

Loading.defaultProps = {
  showHeader: false,
};

export default Loading;
Run Code Online (Sandbox Code Playgroud)

但是,如果有比显示更多的逻辑,或者只是个人偏好,是的,单独的功能是好的:

class Loading extends Component {
  state = {
    error: false,
  };

  componentDidMount = () => {
    this.setTimer();
  };

  componentWillUnmount = () => {
    this.clearTimer();
  };

  setTimer = () => {
    if (this.timerHandle) {
      // Exception?
      return;
    }
    // Remember the timer handle
    this.timerHandle = setTimeout(() => {
      this.setState({ error: true });
      this.timerHandle = 0;
    }, 8000);
  };

  clearTimer = () => {
    // Is our timer running?
    if (this.timerHandle) {
        // Yes, clear it
        clearTimeout(this.timerHandle);
        this.timerHandle = 0;
    }
  };

  render() {
    const { showHeader = false } = this.props;
    const { error } = this.state;
    return (
      <View style={backgroundStyle}>
        {showHeader && <HeaderShell />}
        {!error &&
          <View style={loadingHeight}>
            <PlatformSpinner size="large" />
          </View>}
        {error && <Error code="service" />}
      </View>
    );
  }
}

Loading.propTypes = {
  showHeader: PropTypes.bool,
};

Loading.defaultProps = {
  showHeader: false,
};

export default Loading;
Run Code Online (Sandbox Code Playgroud)


Pur*_*ory 6

您需要清除使用返回的值setTimeout(见下文).但是,这样做clearTimeoutcomponentWillUnmount是做正确的方式,我还没有看到任何人做任何不同.

  componentDidMount = () => {
    this.mounted = true;
    this.timeout = this.timer();
  };

  componentWillUnmount = () => {
    this.mounted = false;
    clearTimeout(this.timeout);
  };

  timer = () =>
    setTimeout(() => {
      (this.mounted && this.setState({ error: true })) || null;
    }, 8000);
Run Code Online (Sandbox Code Playgroud)