我有一些动画,我正在尝试使用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>
);
};
答案 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>
);
}
}