在React和Redux中使用setTimeout

时间:2018-08-31 19:12:13

标签: javascript reactjs redux settimeout

我有一些动画,我正在尝试使用setTimeouts进行工作,由于某些原因,它们反复播放直到时间结束。我有一个可以容纳所有布尔值的reducer和一个可切换它们的动作,但是问题是无论setTimeouts中的条件是否成立,都将触发该动作。我在chrome控制台中查看并确认这是正确的,但我不知道为什么。我将代码放在下面。

type LandingPagePropTypes = {
  displayCommandText: boolean,
  displayInstallText: boolean,
  displayAboutText: boolean,
  displayEnterText: boolean,
  displayWelcomeHeader: boolean,
  togglePropertyInState: (propertyName: string) => void,
  togglePopUpModal: (message: string) => void,
};

const LandingPage = (
  {
    displayWelcomeHeader,
    displayCommandText,
    displayAboutText,
    displayInstallText,
    displayEnterText,
    togglePropertyInState,
    togglePopUpModal,
  }: LandingPagePropTypes,
) => {
  setTimeout(() => {
    if (!displayCommandText) {
      togglePropertyInState('displayCommandText');
    }
  }, 1000);
  setTimeout(() => {
    if (!displayInstallText) {
      togglePropertyInState('displayInstallText');
    }
  }, 3000);
  setTimeout(() => {
    if (!displayAboutText) {
      togglePropertyInState('displayAboutText');
    }
  }, 4000);
  setTimeout(() => {
   if (!displayEnterText) {
      togglePropertyInState('displayEnterText');
    }
  }, 5000);
  setTimeout(() => {
    if (!displayWelcomeHeader) {
      togglePropertyInState('displayWelcomeHeader');
    }
  }, 1000);

  return (
    <div className="landing-page-container">
      <MediaQuery maxWidth={767}>
        <MobileLandingPage
          displayWelcomeHeader={displayWelcomeHeader}
        />
      </MediaQuery>

      <MediaQuery minWidth={768}>
        <DesktopLandingPage
          displayCommandText={displayCommandText}
          displayInstallText={displayInstallText}
          displayAboutText={displayAboutText}
          displayEnterText={displayEnterText}
          togglePopUpModal={togglePopUpModal}
        />
      </MediaQuery>
    </div>
  );
};

2 个答案:

答案 0 :(得分:0)

setTimeout()属于componentDidMount或componentDidUpdate方法。您还需要在componentWillUnmount方法中使用clearTimeout来取消超时,否则,如果在超时触发前卸载组件,则会收到setState on an unmounted component警告。这是一个简化的示例。

class SomeComp extends Component {
  constructor() {...}

  _startAnimation = timeout => {
    this.enterAnimation = setTimeout(
      () => this.setState({ mode: 'entered' }),
      timeout
    )
  }

  componentDidMount() {
    const timeout = someNum

    this._startAnimation(timeout)
  }

  componentWillUnmount() {
    !!this.enterAnimation && clearTimeout(this.enterAnimation)
  }

  render() {...}

}

答案 1 :(得分:0)

我想更新一下我最终做的事情。我想补充一点,我使用的是Flowtype和eslint,并与AirBnB规则配对,因此我不得不对它们进行一些重组以满足它们两个要求。

class LandingPage extends Component <LandingPagePropTypes> {
  constructor(props: LandingPagePropTypes) {
    super(props);
    const { togglePropertyInState } = this.props;

    this.setCommandText = setTimeout(() => togglePropertyInState(
      'displayCommandText'
    ), 1000);
    this.setInstallText = setTimeout(() => togglePropertyInState(
      'displayInstallText'
    ), 3000);
    this.setAboutText = setTimeout(() => togglePropertyInState(
      'displayAboutText'
    ), 4000);
    this.setEnterText = setTimeout(() => togglePropertyInState(
      'displayEnterText'
    ), 5000);
    this.setWelcomeHeader = setTimeout(() => togglePropertyInState(
      'displayWelcomeHeader'
    ), 1000);
  }

  componentWillUnmount() {
    const {
      displayCommandText,
      displayInstallText,
      displayAboutText,
      displayEnterText,
      displayWelcomeHeader,
    } = this.props;

    if (displayCommandText) {
      clearTimeout(this.setCommandText);
    }
    if (displayInstallText) {
      clearTimeout(this.setInstallText);
    }
    if (displayAboutText) {
      clearTimeout(this.setAboutText);
    }
    if (displayEnterText) {
      clearTimeout(this.setEnterText);
    }
    if (displayWelcomeHeader) {
      clearTimeout(this.setWelcomeHeader);
    }
  }

  setCommandText: TimeoutID;

  setInstallText: TimeoutID;

  setAboutText: TimeoutID;

  setEnterText: TimeoutID;

  setWelcomeHeader: TimeoutID;

  render() {
    const {
      displayWelcomeHeader,
      displayCommandText,
      displayAboutText,
      displayInstallText,
      displayEnterText,
      togglePopUpModal,
    } = this.props;


    return (
      <div className="landing-page-container">
        <MediaQuery maxWidth={767}>
          <MobileLandingPage
            displayWelcomeHeader={displayWelcomeHeader}
          />
        </MediaQuery>

        <MediaQuery minWidth={768}>
          <DesktopLandingPage
            displayCommandText={displayCommandText}
            displayInstallText={displayInstallText}
            displayAboutText={displayAboutText}
            displayEnterText={displayEnterText}
            togglePopUpModal={togglePopUpModal}
          />
        </MediaQuery>
      </div>
    );
  }
}