Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应+;Redux:组件在状态更改时未重新提交_Javascript_Reactjs_React Redux_React Hooks - Fatal编程技术网

Javascript 反应+;Redux:组件在状态更改时未重新提交

Javascript 反应+;Redux:组件在状态更改时未重新提交,javascript,reactjs,react-redux,react-hooks,Javascript,Reactjs,React Redux,React Hooks,我正在React上制作一个多人游戏,并使用Colyseus.js作为我的多人API。问题是,我需要在大厅中显示所有连接的玩家: 导出默认函数lobble(){ const classes=useStyles(); const gameState=useSelector(state=>state.roomState); const history=useHistory(); //创建阵列以显示所有连接的玩家 让playerArray=[]; if(Object.entries(gameState)

我正在React上制作一个多人游戏,并使用Colyseus.js作为我的多人API。问题是,我需要在大厅中显示所有连接的玩家:

导出默认函数lobble(){
const classes=useStyles();
const gameState=useSelector(state=>state.roomState);
const history=useHistory();
//创建阵列以显示所有连接的玩家
让playerArray=[];
if(Object.entries(gameState).length!==0){
playerArray=Object.values(gameState.players.toJSON());
}
//检查游戏是否已经开始
useffect(()=>{
log('gamestarted:',gameState.gamestarted);
if(gameState.gameStarted){
历史记录。推送(“/游戏”)
}
},[gameState.gameStarted]);
返回(
{(gameState!=null)?gameState.gameName:}
正在等待所有玩家加入。。。
已连接的玩家:{playersArray.length}
{playersArray.map((数据,索引)=>{
返回(
);
})}
);
}
我使用
useSelector
获取我从Colyseus.js收到的状态,并按如下方式发送(在另一个组件中,
作为子组件在
中进行了调度):

来自服务器的
state
具有带有对象的属性
players
,该对象具有我需要显示的带有播放器名称的键。 我的减速机:

const initialState = {
    joinDetails:{
        gameCode: '',
        partyName: ''
    },
    sessionParams: {
        roomId: "",
        sessionId: "",
    },
    room: {},
    roomState: {},
    scoreChange: null,
    totalChange: null,
    playerState:{
        showResults: false,
        questions: [],
        totalBudget: 5000,
        totalGlobalBudget: 5000,
        budget: [],
        activeStep: 0,
        stepCompleted: [false,false,false,false,false],
        decisions: [-1,-1,-1,-1],

    }

};

function rootReducer(state = initialState, action) {

    switch (action.type) {
        case JOIN_FORM:
            return {...state, joinDetails: action.payload};
        case GAME_ROOM:
            return {...state, room: action.payload};
        case GAME_STATE:
            return {...state, roomState: action.payload};
        case RECONNECT_PARAMS:
            return {...state, sessionParams: action.payload};
        case CHANGE_STEP:
            if(action.payload === 'add'){
                return {...state, playerState: {...state.playerState, activeStep: state.playerState.activeStep + 1}}}
            else{
                return {...state, playerState: {...state.playerState, activeStep: state.playerState.activeStep - 1}}}
        case COMPLETE_STEP:
            return {...state, playerState: {...state.playerState, stepCompleted: action.payload}};
        case SET_BUDGET:
            return {...state, playerState: {...state.playerState, budget: action.payload}};
        case SET_QUESTIONS:
            return {...state, playerState: {...state.playerState, questions: action.payload}};
        case SET_TOTAL_BUDGET:
            if(action.payload.add !== undefined){
                return {...state, playerState: {...state.playerState, totalBudget: state.playerState.totalBudget + action.payload.add}}
            }
            else{
                return {...state, playerState: {...state.playerState, totalBudget: action.payload}};
            }

        case SET_GLOBAL_BUDGET:
            if(action.payload.add !== undefined){
                return {...state, playerState: {...state.playerState, totalGlobalBudget: state.playerState.totalGlobalBudget + action.payload.add}}
            }
            else{
                return {...state, playerState: {...state.playerState, totalGlobalBudget: action.payload}}
            }
        case SET_DECISIONS:
            return {...state, playerState: {...state.playerState, decisions: action.payload}};
        case SET_CHANGES:
            return {...state, scoreChange: action.payload.change, totalChange: action.payload.total};
        case SHOW_RESULTS:
            return {...state, playerState: {...state.playerState, showResults: action.payload}};
        case CLEAR_STATE:
            return {...state, playerState: {}};

        default:
            return state;
    }
}
export default rootReducer;
问题是新玩家加入后,玩家列表不会更新。我可以确认:

  • 我从服务器接收新玩家的状态
  • 我成功地将此状态分派给redux(我通过redux devtools看到它)
  • 看起来lobble()根本就没有重新命名,dispite有
    useSelector
    ,这很有效,因为每个玩家都可以看到在他之前加入的玩家列表
我试着寻找变异状态,但在我看来,那里一切都很好。这是我的第一个redux项目,所以也许我遗漏了什么。 我在redux devtools中注意到一件可疑的事情,即有时(!)最新状态会通过devtools视图中的所有以前的状态传播,例如,“Diff”选项卡显示所有相同的操作都不会导致任何更改,但第一个操作将状态更改为最终形式,例如:

实际变化:

  • 操作将某些属性更改为
  • 操作将某些属性更改为b
  • 操作将某些属性更改为c
显示的变化(但只有在第三次之后才变成这样):

  • 操作将某些属性更改为a,将某些属性更改为b,并将某些属性更改为 属性转换为c
  • 行动没有改变什么
  • 行动没有改变什么
不确定这是否正常或导致我的问题

如果你需要传统代码,请告诉我

谢谢

编辑:根据评论中的建议更改了一些名称,问题仍然存在

编辑2:该问题似乎与使用选择器直接相关:目前我有

gameState = useSelector(state => state.roomState)
但如果我选择整个州,一切都会正常,组件重新加载

gameState = useSelector(state => state)

这远远不够理想:现在我需要调用
gameState.roomState.something
,而不是
gameState.something
。为什么
useSelector
不识别特定部分状态的变化,而只识别整个状态的变化?

所以我的问题是:

room.onStateChange((state) => {
                console.log("the room state has been updated:", state);
                // HERE DISPATCHING RECEIVED STATE
                dispatch({type: GAME_STATE, payload: state });
我将
state
放入有效负载,而没有将其分解/复制到新对象,因此实际上只传递一个引用。当然,当它被改变的时候,它也改变了所有其他的参考,没有什么可以比较的。正确的方法是在将接收的
状态
传递给操作时对其进行分解:

room.onStateChange((state) => {
                console.log("the room state has been updated:", state);
                // HERE DISPATCHING RECEIVED STATE
                dispatch({type: GAME_STATE, payload: {...state} })

尝试将useSelector更改为-{const gameState=useSelector(state=>state);}或从您的initialState@HagaiHarari你是说把整个州都还回去?现在我从state返回“state”键,可能是命名导致了问题?好的,所以我更好地查看了您的代码,并在您的initialState“state”方法中看到了state.state引用的方法。但可能会以不同的方式将其称为“myState”,因为例如这里{…state,“joinDetails”:action.payload}}joinDetails假设没有“@HagaiHarari i更改了命名,删除了引号,但仍然不起作用:state set,但lobble未重新命名。。。因此,我的代码中没有其他明显错误的地方了?如果我理解正确,除了用户a和用户b加入,用户b看到的是用户a,而不是周围的另一面,所有的工作都如预期的那样,对吗?如果是这样,您是否考虑过将Socket.io添加到项目中?
room.onStateChange((state) => {
                console.log("the room state has been updated:", state);
                // HERE DISPATCHING RECEIVED STATE
                dispatch({type: GAME_STATE, payload: {...state} })