Использование setTimeout с React и Redux - PullRequest
0 голосов
/ 31 августа 2018

У меня есть некоторые анимации, которые я пытаюсь запустить, используя setTimeouts, и по какой-то причине они запускаются снова и снова до конца времени. У меня есть редуктор, который содержит все мои логические значения, и действие, которое их переключает, но проблема в том, что действие запускается независимо от того, выполняется ли условие в 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 голосов
/ 01 сентября 2018

Я хотел узнать, что я в итоге делал. Я хочу добавить, что я использую 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>
    );
  }
}
0 голосов
/ 31 августа 2018

setTimeout() принадлежит методам componentDidMount или componentDidUpdate. Вам также понадобится clearTimeout в методе componentWillUnmount для отмены тайм-аута, или вы получите предупреждение 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() {...}

}
...