全局状态更改时组件不会重新渲染。 React Redux 工具包

问题描述 投票:0回答:1

我正在开发 Mafia 应用程序,以实现游戏管理员工作的自动化。我有一个 UserPanel 组件,它显示所有球员、他们的数量和犯规次数。 UserPanel

我还有一个 AdminPanel 组件,它由 ControlPanel 组件、MiddlePanel 组件和 VotingPanel 组件组成。这是AdminPanel组件的屏幕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
javascript reactjs redux-toolkit
1个回答
0
投票

如果返回组件数组,则需要将

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。另外,请抵制使用地图索引作为键的冲动。这可以工作,但也可能导致难以发现错误。

© www.soinside.com 2019 - 2024. All rights reserved.