Javascript 仅在一个组件中调用方法

Javascript 仅在一个组件中调用方法,javascript,reactjs,Javascript,Reactjs,我在主页组件的web应用程序上有一个计时器,它正在进行倒计时。以下是主页组件: export default class Home extends React.Component { timer() { var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime(); var x = setInterval(() => { var now = new Date(

我在主页组件的web应用程序上有一个计时器,它正在进行倒计时。以下是
主页
组件:

export default class Home extends React.Component {

    timer() {
        var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
        var x = setInterval(() => {

            var now = new Date().getTime();

            var distance = countDownDate - now;

            var days = Math.floor(distance / (1000 * 60 * 60 * 24));
            var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
            var seconds = Math.floor((distance % (1000 * 60)) / 1000);

            document.getElementById("timer").innerHTML = days + "d " + hours + "h "
                + minutes + "m " + seconds + "s ";

            if (distance < 0) {
                clearInterval(x);
                document.getElementById("timer").innerHTML = "EXPIRED";
            }
        }, 1000);
    }

    componentDidMount() {
        $('.monster').fadeIn('slow');
        this.timer();
    }


    render() {
        return (
            <div id="timer"></div>
        )
    }
}
export default class AssignmentsComponent extends React.Component {
    render() {
        return (
            <h1>Questions Component</h1>
        )
    }
}
export default class App extends Component {
    render() {
        return (
            <div className="App">
                <NavigationComponent {...this}/>
                {/*<CheckIfHasCurrentTasksComponent user={firebase.auth().currentUser}/>*/}
                {/*{this.state.user ? <Questions/> : <Home/>}*/}
            </div>
        );
    }
}
export default class NavigationComponent extends React.Component {

    render() {
        return (
            <BrowserRouter>
                <React.Fragment>
                    <Navbar className="fixedTop custom_navbar half_transparent">
                        <Nav className="float_right">
                            <NavItem className="custom_button_navbar"><span>pobierz</span></NavItem>

                            {
                                firebase.auth().currentUser !== null ?
                                    <React.Fragment>
                                        <LinkContainer id="assignments" to='/assignments'>
                                            <NavItem>Zadania</NavItem>
                                        </LinkContainer>
                                        <NavItem onClick={logout.bind(this)}>Wyloguj się</NavItem>
                                    </React.Fragment>
                                    :
                                    <NavItem onClick={this.openLogin}
                                             className="custom_button_navbar"><span>Zaloguj się</span></NavItem>
                            }

                        </Nav>
                    </Navbar>
                    <Switch>
                        <Route exact path="/assignments" render={
                            () => (firebase.auth().currentUser === null ?
                                <Redirect to='/'/> : <AssignmentsComponent/>)
                        }/>

                        <Route exact path='/assignment/:id' render={
                            props => (
                                firebase.auth().currentUser === null ?
                                    <Redirect to='/'/> : <CheckIfHasCurrentTasksComponent {...props}/>
                            )
                        }/>

                        <Route exact path="/" component={HomeComponent}/>
                    </Switch>
                    <LoginFormComponent show={this.state.show} changeShowState={this.changeShowState}/>
                </React.Fragment>
            </BrowserRouter>
        )
    }
}
这是我的
App.js
组件:

export default class Home extends React.Component {

    timer() {
        var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
        var x = setInterval(() => {

            var now = new Date().getTime();

            var distance = countDownDate - now;

            var days = Math.floor(distance / (1000 * 60 * 60 * 24));
            var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
            var seconds = Math.floor((distance % (1000 * 60)) / 1000);

            document.getElementById("timer").innerHTML = days + "d " + hours + "h "
                + minutes + "m " + seconds + "s ";

            if (distance < 0) {
                clearInterval(x);
                document.getElementById("timer").innerHTML = "EXPIRED";
            }
        }, 1000);
    }

    componentDidMount() {
        $('.monster').fadeIn('slow');
        this.timer();
    }


    render() {
        return (
            <div id="timer"></div>
        )
    }
}
export default class AssignmentsComponent extends React.Component {
    render() {
        return (
            <h1>Questions Component</h1>
        )
    }
}
export default class App extends Component {
    render() {
        return (
            <div className="App">
                <NavigationComponent {...this}/>
                {/*<CheckIfHasCurrentTasksComponent user={firebase.auth().currentUser}/>*/}
                {/*{this.state.user ? <Questions/> : <Home/>}*/}
            </div>
        );
    }
}
export default class NavigationComponent extends React.Component {

    render() {
        return (
            <BrowserRouter>
                <React.Fragment>
                    <Navbar className="fixedTop custom_navbar half_transparent">
                        <Nav className="float_right">
                            <NavItem className="custom_button_navbar"><span>pobierz</span></NavItem>

                            {
                                firebase.auth().currentUser !== null ?
                                    <React.Fragment>
                                        <LinkContainer id="assignments" to='/assignments'>
                                            <NavItem>Zadania</NavItem>
                                        </LinkContainer>
                                        <NavItem onClick={logout.bind(this)}>Wyloguj się</NavItem>
                                    </React.Fragment>
                                    :
                                    <NavItem onClick={this.openLogin}
                                             className="custom_button_navbar"><span>Zaloguj się</span></NavItem>
                            }

                        </Nav>
                    </Navbar>
                    <Switch>
                        <Route exact path="/assignments" render={
                            () => (firebase.auth().currentUser === null ?
                                <Redirect to='/'/> : <AssignmentsComponent/>)
                        }/>

                        <Route exact path='/assignment/:id' render={
                            props => (
                                firebase.auth().currentUser === null ?
                                    <Redirect to='/'/> : <CheckIfHasCurrentTasksComponent {...props}/>
                            )
                        }/>

                        <Route exact path="/" component={HomeComponent}/>
                    </Switch>
                    <LoginFormComponent show={this.state.show} changeShowState={this.changeShowState}/>
                </React.Fragment>
            </BrowserRouter>
        )
    }
}
问题是:当我打开home组件时,一切都很顺利,计时器启动,一切都很好。但是如果我转到questions组件,
timer()
方法仍在尝试运行,即使我没有在
Assignments
组件中的任何地方调用它。这就是应用程序崩溃的时候

在timer()方法中添加
try catch
块,如下所示:

try {
    document.getElementById("timer").innerHTML = days + "d " + hours + "h "
        + minutes + "m " + seconds + "s ";

    if (distance < 0) {
        clearInterval(x);
        document.getElementById("timer").innerHTML = "EXPIRED";
    }
} catch (e) {

}
试试看{
document.getElementById(“计时器”).innerHTML=days+“d”+hours+“h”
+分钟+米+秒+秒;
如果(距离<0){
净间隔(x);
document.getElementById(“计时器”).innerHTML=“过期”;
}
}捕获(e){
}
解决了这个问题,但我敢肯定这是一个糟糕的做法


因此,如何使其仅在呈现
组件时调用?

当组件卸载时,应删除计时器。您可以在
Home
组件的
componentWillUnmount()
生命周期方法中执行此操作

见:


卸载组件时,应移除计时器。您可以在
Home
组件的
componentWillUnmount()
生命周期方法中执行此操作

见:


这确实需要减少到a(注意“最小值”)。理想情况下,使用堆栈片段(
[]
工具栏按钮)使其成为可运行的MCVE。堆栈代码段支持React,包括JSX。好的,给我几分钟时间尝试移除
组件中的计时器将卸载
主页中的
组件。谢谢@Winter!您想添加它作为答案吗?当然,我现在已经添加了。:)这确实需要减少到(注意“最小”)。理想情况下,使用堆栈片段(
[]
工具栏按钮)使其成为可运行的MCVE。堆栈代码段支持React,包括JSX。好的,给我几分钟时间尝试移除
组件中的计时器将卸载
主页中的
组件。谢谢@Winter!您想添加它作为答案吗?当然,我现在已经添加了。:)