I have a dynamic Countdown Timer In React:
This Timer is a component (MovementTimer.js) & the main component (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="welcome">
{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="welcome"> {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 component
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 component, 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.
CodePudding user response:
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