Charlotte Cheng
Charlotte Cheng

Reputation: 37

(React)Child component pause its useEffect when the parent re-renders

Edit: This problem has been solved by adding a second parameter in the useEffect Hooks.

I am new to react and am building a toy react game. I borrowed this timer I found here. If user performs an action and the parent component re-renders, the timer stop counting down for a short period of time. According to (https://reactjs.org/docs/hooks-effect.html), react will remember the useEffect function, and call it later after performing the DOM updates. If that's the reason, are there any solutions or alternatives to this? If not, can anyone point me in the right direction? Any help will be appreciated!

Here is my code snippet for reference:

class Chalkboard extends Component {
    constructor(props) {
        super(props);
        this.state = {
            minutes: 1,
            seconds: 0,
            addSeconds: 0,
        };
    }

    updateTimer() {
        this.setState({ addSeconds: 0 });
    }

    handleTimer() {
        window.removeEventListener('keydown', this.keyHandling);
        this.setState({
            gameOver: true,
        });
    }

    render() {
       return(
           <Timer
                initialMinutes={this.state.minutes}
                initialSeconds={this.state.seconds}
                onTimer={this.handleTimer}
                addSeconds={this.state.addSeconds}
                updateTimer={this.updateTimer}
            />
           )

}
import React, { useState, useEffect } from 'react';

const Timer = (props) => {
    const { initialMinutes = 0, initialSeconds = 0 } = props;
    const [minutes, setMinutes] = useState(initialMinutes);
    const [seconds, setSeconds] = useState(initialSeconds);

    useEffect(() => {
        let myInterval = setInterval(() => {
            if (seconds > 0) {
                setSeconds(seconds - 1);
            }
            else if (seconds === 0) {
                if (minutes === 0) {
                    clearInterval(myInterval);
                } else {
                    setSeconds(59);
                    setMinutes(minutes - 1);
                }
            }
        }, 1000);
        return () => {
            clearInterval(myInterval);
        };
    });

    useEffect(() =>{
        if(props.addSeconds>0){
            setSeconds(seconds + props.addSeconds);
            props.updateTimer()
        }
        if(minutes === 0 && seconds === 0){
            props.onTimer()
        }
    });


    return (
        <div className = "timer-container" >
            {minutes === 0 && seconds === 0 ? null: (
                <div>
                    {' '}
                    {minutes}:{seconds < 10 ? `0${seconds}` : seconds}
                </div>
            )}
        </div>
    );
};

export default Timer;

Upvotes: 0

Views: 552

Answers (1)

Ivan Stelmakh
Ivan Stelmakh

Reputation: 644

Can you provide an example on https://codesandbox.io/?

Try to pass [props, minutes, seconds] as a second parameter in useEffect hook. https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

Upvotes: 0

Related Questions