Javascript 反应+;Redux:组件在状态更改时未重新提交
我正在React上制作一个多人游戏,并使用Colyseus.js作为我的多人API。问题是,我需要在大厅中显示所有连接的玩家: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)
导出默认函数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} })