React dispatch & useSelector doesn't update

huangapple go评论65阅读模式
英文:

React dispatch & useSelector doesn't update

问题

以下是翻译好的代码部分:

export const startGame = () => {
    // 设置游戏状态为进行中
    return { type: 'START_GAME', payload: true };
}

export const rollDices = (userIds) => {
    // 掷骰子
    return { type: "ROLL_DICE", payload: userIds };
}
import { useState } from "react";
import { useDispatch } from 'react-redux';

import { useAuth } from "../../contexts/AuthContext";
import { startGame, rollDices } from "../../services/store/action";
import { Game } from "./Game";

export const GameArea = ({ socket, userIds, host }) => {
    const [inGame, setInGame] = useState(false);

    const { currentUser } = useAuth();
    const dispatch = useDispatch();

    const handleStartGame = () => {
        // 设置游戏状态为进行中
        setInGame(true);
        dispatch(startGame());
        dispatch(rollDices(userIds));
    }

    if(!inGame) {
        console.log(currentUser.uid);
        console.log(host);
        if(currentUser.uid === host) {
            return (
                <button
                    className="mainButton"
                    id="startButton"
                    onClick={handleStartGame}
                >开始游戏</button>
            );
        }else {
            return (<p id="waitingMsg">等待主持人开始游戏...</p>);
        }
    }else {
        return (
            <Game socket={socket} />
        );
    }
}

请注意,代码中的注释已经进行了中文翻译。希望这对你有所帮助。如果你有任何其他问题或需要进一步的帮助,请随时提问。

英文:

I have part of action.js like:

export const startGame = () =&gt; {
    // set game state to ongoing game
    return { type: &#39;START_GAME&#39;, payload: true };
}

export const rollDices = (userIds) =&gt; {
    // roll dices
    return { type: &quot;ROLL_DICE&quot;, payload: userIds };
}

and I use it in GameArea.js like:

import { useState } from &quot;react&quot;;
import { useDispatch } from &#39;react-redux&#39;;

import { useAuth } from &quot;../../contexts/AuthContext&quot;;
import { startGame, rollDices } from &quot;../../services/store/action&quot;;
import { Game } from &quot;./Game&quot;;

export const GameArea = ({ socket, userIds, host }) =&gt; {
    const [inGame, setInGame] = useState(false);

    const { currentUser } = useAuth();
    const dispatch = useDispatch();

    const handleStartGame = () =&gt; {
        // set game state to ongoing game
        setInGame(true);
        dispatch(startGame());
        dispatch(rollDices(userIds));
    }

    if(!inGame) {
        console.log(currentUser.uid);
        console.log(host);
        if(currentUser.uid === host) {
            return (
                &lt;button
                    className=&quot;mainButton&quot;
                    id=&quot;startButton&quot;
                    onClick={handleStartGame}
                &gt;Start Game&lt;/button&gt;
            );
        }else {
            return (&lt;p id=&quot;waitingMsg&quot;&gt;Waiting for the host to&lt;br/&gt;start the game...&lt;/p&gt;);
        }
    }else {
        return (
            &lt;Game socket={socket} /&gt;
        );
    }
}

The GameArea.js is included in Room.js, which I think it may not be important in this question. However, when I test it with 2 accounts in different tabs, one can still join the room even if the start game button is pressed in that room, which, I think, means that the inGame is not updated as true at this point somehow.

Also if another use is in the room while the host press the start game button, the interface doesn't update as game started for him/her.

I wonder how can I fix this?

答案1

得分: 0

为了解决这个问题,您可以使用useEffect钩子来监听inGame状态的变化,并相应地更新组件。以下是已经更新过的GameArea组件,包含必要的更改:

import { useState, useEffect } from "react";
import { useDispatch } from 'react-redux';

import { useAuth } from "../../contexts/AuthContext";
import { startGame, rollDices } from "../../services/store/action";
import { Game } from "./Game";

export const GameArea = ({ socket, userIds, host }) => {
    const [inGame, setInGame] = useState(false);

    const { currentUser } = useAuth();
    const dispatch = useDispatch();

    const handleStartGame = () => {
        // 将游戏状态设置为正在进行中
        setInGame(true);
        dispatch(startGame());
        dispatch(rollDices(userIds));
    }

    useEffect(() => {
        // 监听`inGame`状态的变化
        // 并相应地更新组件
        if (inGame) {
            // 游戏已经开始,执行某些操作
        } else {
            // 游戏尚未开始,执行其他操作
        }
    }, [inGame]);

    if (!inGame) {
        console.log(currentUser.uid);
        console.log(host);
        if (currentUser.uid === host) {
            return (
                <button
                    className="mainButton"
                    id="startButton"
                    onClick={handleStartGame}
                >
                    开始游戏
                </button>
            );
        } else {
            return (
                <p id="waitingMsg">
                    等待主持人开始游戏...
                </p>
            );
        }
    } else {
        return <Game socket={socket} />;
    }
}

请注意,我已经将代码部分保留为英文,只翻译了注释和字符串。如果您需要进一步的帮助,请随时提出。

英文:

To fix this issue, you can use the useEffect hook to listen for changes in the inGame state and update the component accordingly. Here's an updated version of your GameArea component with the necessary changes:

import { useState, useEffect } from &quot;react&quot;;
import { useDispatch } from &#39;react-redux&#39;;
import { useAuth } from &quot;../../contexts/AuthContext&quot;;
import { startGame, rollDices } from &quot;../../services/store/action&quot;;
import { Game } from &quot;./Game&quot;;
export const GameArea = ({ socket, userIds, host }) =&gt; {
const [inGame, setInGame] = useState(false);
const { currentUser } = useAuth();
const dispatch = useDispatch();
const handleStartGame = () =&gt; {
// set game state to ongoing game
setInGame(true);
dispatch(startGame());
dispatch(rollDices(userIds));
}
useEffect(() =&gt; {
// Listen for changes in the inGame state
// and update the component accordingly
if (inGame) {
// Game has started, do something
} else {
// Game has not started, do something else
}
}, [inGame]);
if (!inGame) {
console.log(currentUser.uid);
console.log(host);
if (currentUser.uid === host) {
return (
&lt;button
className=&quot;mainButton&quot;
id=&quot;startButton&quot;
onClick={handleStartGame}
&gt;
Start Game
&lt;/button&gt;
);
} else {
return (
&lt;p id=&quot;waitingMsg&quot;&gt;
Waiting for the host to&lt;br /&gt;start the game...
&lt;/p&gt;
);
}
} else {
return &lt;Game socket={socket} /&gt;;
}
}

答案2

得分: 0

@Sumith在评论中是正确的,我需要将信息传递到服务器端,以便其他用户可以获得此信息,以决定是否可以加入房间。

英文:

@Sumith in the comment is correct that I need to pass the info to the server side so that other users can have this info to decide if they can join the room

huangapple
  • 本文由 发表于 2023年7月17日 16:13:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76702583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定