admin管理员组

文章数量:1414613

I have a dynamic Countdown Timer In React:

This Timer is a ponent (MovementTimer.js) & the main ponent (GameRoom.js) is calling Timer's render method, passing thru props.

This is the render Timer function that's being called below upon every GameRoom render

    renderTimer = () => {
        console.log('*** Timer RERENDER ***');
        console.log(this.state.turn_time);
        console.log(this.state.last_time);

        if(this.state.turn_time != null && this.state.last_time != null){
            const props = {
                time : this.state.turn_time,
                last_time : this.state.last_time

            }

            return(
                <MovementTimer {...props}/>
            )
        } else {
            return(
                <p>Undefined Timer.</p>
            )
        }
    }

This is the render method of GameRoom.js

   render() {

        if(this.state.guest){
            console.log('loaded in ! ' + this.state.guest);
            //              Put into return statement for DEBUG     {this.state.turn ? "TRUE" : "FALSE"} 
            return (
                <div className="main">
                    {this.renderBoard()}
                    {this.renderTimer()}

                    {}
                    <p className="wele"> 

                    {this.state.userResponseData}

                    {
                    this.state.guest[0] ? (this.state.turn ? "It's your opponent's turn." : "It's your turn, move!") : (this.state.turn ? "It's your turn, move!" : "It's your opponent's turn.")
                    
                    }</p>
    
                </div>
            )
        }

        return (
            <div className="main">
                {this.renderBoard()}
                
                <p className="wele"> {this.state.turn ? "TRUE" : "FALSE"} Loading {this.state.userResponseData}</p>

            </div>
        )
    }
}

Basically the issue is, whenever GameRoom.js rerender's, the renderTimer() function passes in updated props to the MovementTimer, however the timer doesn't reset. I was trying to use a useRef state boolean but it was buggy and wasn't working.

MovementTimer.js ponent

import React, {useRef, clearState,useState,useCallback} from 'react'


const MovementTimer = (props) => {
    console.log('Re initizalized')
    const time = parseInt(props.time);
    const last_time = parseInt(props.last_time);

    //clearState()
    console.log( 

        "Estimated Time:\n"+
        ((last_time+time*1000) - Date.now() )/1000
        
    );

    let [counter, setCounter] = React.useState(Math.round( ((last_time+time*1000) - Date.now() )/1000 ) );
    // const reinit = () => {
    //     setCounter(time)
    // }

    console.log(counter);
    console.log(last_time);

    React.useEffect(() => {

        counter > 0 && setTimeout(() => setCounter(
            counter - 1
        ), 1000); //Set this too Due time - last time / 1000 (for secs)

        
        if(counter === 0){
            const socketProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    
            const socket = new WebSocket(socketProtocol+(window.location.href).split(':')[1]+':5000');
    
            socket.onopen = async () => {
                await socket.send(JSON.stringify({
                    query_type : 't0',
                    room_id: (window.location.pathname).slice(6)
                }));
                socket.close();
                
    
            }
            setCounter(Math.round( ((last_time+time*1000) - Date.now() )/1000 ))
        }    



      }, [counter]);
    


    return (
        <div>
            {counter}
        </div>
    )
}

export default MovementTimer

In this ponent, I useEffect for the timer countdown, and pass in the time difference in seconds (using props that have been passed down) Is there anyway to check if props change, and reset the useEffect?

In that if statement (counter === 0), I manually set it back using setCounter. however i dont know how to check for prop change. whenever last_time prop is updated.

I have a dynamic Countdown Timer In React:

This Timer is a ponent (MovementTimer.js) & the main ponent (GameRoom.js) is calling Timer's render method, passing thru props.

This is the render Timer function that's being called below upon every GameRoom render

    renderTimer = () => {
        console.log('*** Timer RERENDER ***');
        console.log(this.state.turn_time);
        console.log(this.state.last_time);

        if(this.state.turn_time != null && this.state.last_time != null){
            const props = {
                time : this.state.turn_time,
                last_time : this.state.last_time

            }

            return(
                <MovementTimer {...props}/>
            )
        } else {
            return(
                <p>Undefined Timer.</p>
            )
        }
    }

This is the render method of GameRoom.js

   render() {

        if(this.state.guest){
            console.log('loaded in ! ' + this.state.guest);
            //              Put into return statement for DEBUG     {this.state.turn ? "TRUE" : "FALSE"} 
            return (
                <div className="main">
                    {this.renderBoard()}
                    {this.renderTimer()}

                    {}
                    <p className="wele"> 

                    {this.state.userResponseData}

                    {
                    this.state.guest[0] ? (this.state.turn ? "It's your opponent's turn." : "It's your turn, move!") : (this.state.turn ? "It's your turn, move!" : "It's your opponent's turn.")
                    
                    }</p>
    
                </div>
            )
        }

        return (
            <div className="main">
                {this.renderBoard()}
                
                <p className="wele"> {this.state.turn ? "TRUE" : "FALSE"} Loading {this.state.userResponseData}</p>

            </div>
        )
    }
}

Basically the issue is, whenever GameRoom.js rerender's, the renderTimer() function passes in updated props to the MovementTimer, however the timer doesn't reset. I was trying to use a useRef state boolean but it was buggy and wasn't working.

MovementTimer.js ponent

import React, {useRef, clearState,useState,useCallback} from 'react'


const MovementTimer = (props) => {
    console.log('Re initizalized')
    const time = parseInt(props.time);
    const last_time = parseInt(props.last_time);

    //clearState()
    console.log( 

        "Estimated Time:\n"+
        ((last_time+time*1000) - Date.now() )/1000
        
    );

    let [counter, setCounter] = React.useState(Math.round( ((last_time+time*1000) - Date.now() )/1000 ) );
    // const reinit = () => {
    //     setCounter(time)
    // }

    console.log(counter);
    console.log(last_time);

    React.useEffect(() => {

        counter > 0 && setTimeout(() => setCounter(
            counter - 1
        ), 1000); //Set this too Due time - last time / 1000 (for secs)

        
        if(counter === 0){
            const socketProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    
            const socket = new WebSocket(socketProtocol+(window.location.href).split(':')[1]+':5000');
    
            socket.onopen = async () => {
                await socket.send(JSON.stringify({
                    query_type : 't0',
                    room_id: (window.location.pathname).slice(6)
                }));
                socket.close();
                
    
            }
            setCounter(Math.round( ((last_time+time*1000) - Date.now() )/1000 ))
        }    



      }, [counter]);
    


    return (
        <div>
            {counter}
        </div>
    )
}

export default MovementTimer

In this ponent, I useEffect for the timer countdown, and pass in the time difference in seconds (using props that have been passed down) Is there anyway to check if props change, and reset the useEffect?

In that if statement (counter === 0), I manually set it back using setCounter. however i dont know how to check for prop change. whenever last_time prop is updated.

Share Improve this question asked Feb 15, 2022 at 13:26 jasonmzxjasonmzx 5275 silver badges17 bronze badges 1
  • just on first look, you are setting your counter wrong way... if you changing state in async function, you should use callback for this: counter > 0 && setTimeout(() => setCounter((prevCount)=> prevCount - 1), 1000); – Wraithy Commented Feb 15, 2022 at 13:32
Add a ment  | 

1 Answer 1

Reset to default 3

The second parameter in your useEffect is what the function listens to for changes. If you just want to rerun the function in useEffect when a specific variable changes, add it to the array. For example, if you want to rerun it when variable x changes, you would write it like this:

React.useEffect(() => { /* do stuff */ }, [counter, x]);

Documentation: Conditionally firing an effect

本文标签: javascriptReact Component UseEffect isn39t rerendering upon prop changeStack Overflow