我正在开发 Mafia 应用程序,以实现游戏管理员工作的自动化。我有一个 UserPanel 组件,它显示所有球员、他们的数量和犯规次数。
我还有一个 AdminPanel 组件,它由 ControlPanel 组件、MiddlePanel 组件和 VotingPanel 组件组成。这是AdminPanel组件的屏幕
我遇到的问题是当我在管理面板上犯规时。它显示在此处,但不在用户面板上。我应该注意到我正在使用react-router-dom,UserPanel位于localhost:3000,AdminPanel位于localhost:3000/admin。我不知道为什么会这样,因为UserPanel和MiddlePanel订阅了gameSlice全局状态。这是 UserPanel 组件代码:
import React from "react";
import Player from "./Player";
import Timer from "./Timer";
import { useSelector } from "react-redux";
export default function UserPanel() {
const players = useSelector((state) => state.gameReducer.players);
return (
<div className="user-panel">
<div className="container">
<h1>Mafia NUZP</h1>
<div className="players-container">
{players.map(player => {
return <Player number={player.number} fouls={player.fouls} chosen={player.chosen}/>
})}
</div>
<Timer />
</div>
</div>
)
}
中面板代码:
import React from "react";
import Player from "../../Player";
import Role from "../../Role";
import Timer from "../../Timer";
import TimerControls from "./TimerControls";
import { useSelector } from "react-redux";
export default function MiddlePanel(props) {
const players = useSelector((state) => state.gameReducer.players);
let chosenPlayer = players.findIndex(player => player.chosen === true);
return(
<div className="middle-panel">
<div className="chosen-player-container">
<h1>Player {chosenPlayer + 1}</h1>
</div>
<div className="players-container">
{players.map(player => {
return <Player number={player.number} role={<Role role={player.role}/>} fouls={player.fouls} chosen={player.chosen}/>
})}
</div>
<div className="timer-container">
<Timer />
<TimerControls />
</div>
</div>
)
}
控制面板代码:
import React from "react";
import { setFoul, setRole } from "../../features/game/gameSlice";
import { useDispatch } from "react-redux";
export default function ControlPanel() {
const dispatch = useDispatch();
return(
<div className="control-panel">
<button className="btn btn-dark" onClick={() => dispatch(setRole({role: "Д"}))}>Сделать доном</button>
<button className="btn btn-secondary" onClick={() => dispatch(setRole({role: "М"}))}>Сделать мафией</button>
<button className="btn btn-warning" onClick={() => dispatch(setRole({role: "Ш"}))}>Сделать шерифом</button>
<button className="btn btn-danger" onClick={() => dispatch(setRole({role: "К"}))}>Сделать мирным</button>
<button className="btn btn-light" onClick={() => dispatch(setFoul())}>Поставить фол</button>
<button className="btn btn-primary">Выставить на голосование</button>
<button className="btn btn-danger">Изгнать</button>
<button className="btn btn-info">Следующий игрок</button>
<button className="btn btn-info">Предыдущий игрок</button>
</div>
)
}
还有游戏切片代码:
import { createSlice } from "@reduxjs/toolkit";
let players = [
{number: 1, fouls: [null, null, null, null], role: null, chosen: false},
{number: 2, fouls: [null, null, null, null], role: null, chosen: false},
{number: 3, fouls: [null, null, null, null], role: null, chosen: false},
{number: 4, fouls: [null, null, null, null], role: null, chosen: false},
{number: 5, fouls: [null, null, null, null], role: null, chosen: false},
{number: 6, fouls: [null, null, null, null], role: null, chosen: true},
{number: 7, fouls: [null, null, null, null], role: null, chosen: false},
{number: 8, fouls: [null, null, null, null], role: null, chosen: false},
{number: 9, fouls: [null, null, null, null], role: null, chosen: false},
{number: 10, fouls: [null, null, null, null], role: null, chosen: false}]
let admin = {
}
const initialState = {
players: players,
adminPanel: admin
}
const gameSlice = createSlice({
name: "game",
initialState,
reducers: {
setRole(state, action) {
let {role} = action.payload
let chosenIndex = state.players.findIndex(player => player.chosen === true);
state.players[chosenIndex].role = role;
},
setFoul(state, action) {
let chosenIndex = state.players.findIndex(player => player.chosen === true);
let foulIndex = state.players[chosenIndex].fouls.findIndex(foul => foul === null);
state.players[chosenIndex].fouls[foulIndex] = "F";
},
}
})
export const {setFoul, setRole} = gameSlice.actions
export default gameSlice.reducer
如果返回组件数组,则需要将
key
属性传递给这些组件,以便 React 可以跟踪它们。
{players.map(player => {
return <Player key={player.number} number={player.number} role={<Role role={player.role}/>} fouls={player.fouls} chosen={player.chosen}/>
})}
一旦传递了 key prop,react 将能够正确跟踪数组中每个组件的状态。
key
需要是一个完全唯一的值,不会与数组中的任何其他项重复。通常,键是数据库中值的 ID。另外,请抵制使用地图索引作为键的冲动。这可以工作,但也可能导致难以发现错误。