React Component UseEffect 不会在 prop 更改时重新渲染

React Component UseEffect isn't rerendering upon prop change

我在 React 中有一个动态倒数计时器:

这个 Timer 是一个组件 (MovementTimer.js) 并且主要组件 (GameRoom.js) 正在调用 Timer 的 render 方法,通过 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>
        )
    }
}

基本上问题是,每当 GameRoom.js 重新渲染时,renderTimer() 函数将更新的道具传递给 MovementTimer,但是计时器不会重置。我试图使用 useRef 状态布尔值,但它有问题并且无法正常工作。

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

这个组件里,我用useEffect做定时器倒计时,传入时差秒数(使用传下来的props) 有没有办法检查props是否变化,重新设置useEffect?

在那条 if 语句中(计数器 === 0),我使用 setCounter 手动将其设置回去。但是我不知道如何检查道具的变化。每当 last_time 道具更新时。

您的 useEffect 中的第二个参数是函数侦听更改的内容。如果您只想在特定变量更改时重新运行 useEffect 中的函数,请将其添加到数组中。例如,如果你想在变量 x 改变时重新运行它,你可以这样写:

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

文档:Conditionally firing an effect