在React中数组的意外突变。

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

我刚刚学会编程,正在用React编写我的第一个应用程序之一。我遇到了一个意想不到的突变问题,但我找不到根源。这段代码是一个功能组件的一部分,内容如下。

const players = props.gameList[gameIndex].players.map((item, index) => {
    const readyPlayer = [];
    props.gameList[gameIndex].players.forEach(item => {
      readyPlayer.push({
        id: item.id,
        name: item.name,
        ready: item.ready
      })
    })
    console.log(readyPlayer);
    readyPlayer[index].test = "test";
    console.log(readyPlayer);
    return (
      <li key={item.id}>
        {/* not relevant to the question */}
      </li>
    )
  })

现在的问题是,readyPlayer似乎在它应该被突变之前就被突变了。两个console.log的读取结果都是一样的。forEach并没有突变原始数组,所有的键值,即id、name和ready,都是布尔或字符串的基元。我在这里也没有实现任何异步操作,为什么会得到这样的输出?如果有任何帮助,将非常感谢。

下面是整个组件的原始组成,供参考(这里也将测试键替换成了我需要的实际键,但无论如何,问题依然存在。

import React from 'react';

import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
// import styles from './Lobby.module.css';

const Lobby = ( props ) => {

  const gameIndex = props.gameList.findIndex(item => item.id === props.current.id);
  const isHost = props.gameList[gameIndex].hostId === props.user.uid;

  const players = props.gameList[gameIndex].players.map((item, index) => {
    const isPlayer = item.id === props.user.uid;
    const withoutPlayer = [...props.gameList[gameIndex].players];
    withoutPlayer.splice(index, 1);
    const readyPlayer = [];
    props.gameList[gameIndex].players.forEach(item => {  
      readyPlayer.push({
        id: item.id,
        name: item.name,
        ready: item.ready
      })
    })
    const isReady = readyPlayer[index].ready;
    console.log(readyPlayer);
    console.log(!isReady);
    readyPlayer[index].ready = !isReady;
    console.log(readyPlayer);
    return (
      <li key={item.id}>
        {isHost && index !== 0 && <button onClick={() => props.updatePlayers(props.gameList[gameIndex].id, withoutPlayer)}>Kick Player</button>}
        <p>{item.name}</p>
        {isPlayer && <button onClick={() =>props.updatePlayers(props.gameList[gameIndex].id, readyPlayer)}>Ready</button>}
      </li>
    )
  })

  let showStart = props.gameList[gameIndex].players.length >= 2;
  props.gameList[gameIndex].players.forEach(item => {
    if (item.ready === false) {
      showStart = false;
    }
  })

  console.log(showStart);

  return (
    <main>
      <div>
        {showStart && <Link to="/gameboard" onClick={props.start}>Start Game</Link>}
        <Link to="/main-menu">Go back to Main Menu</Link>
      </div>
      <div>
        <h3>Players: {props.gameList[gameIndex].players.length}/4</h3>
         {players}
      </div>
    </main>
  );
}

Lobby.propTypes = {
  start: PropTypes.func.isRequired,
  current: PropTypes.object.isRequired,
  gameList: PropTypes.array.isRequired,
  updatePlayers: PropTypes.func.isRequired,
  user: PropTypes.object.isRequired

}

export default Lobby;

注:我确实做到了让组件真正做到了它应该做的事情,但上述意外的突变依然存在,对我来说依然是个谜。

javascript reactjs immutability
1个回答
0
投票

我已经使用你提供的代码片段创建了一个基本的工作示例。两个 console.log 语句在这里返回不同的值。第一个语句返回的是 readyPlayer.test 作为 undefined第二项为 "test". 你确定这个问题发生在你的代码片段中吗?还是我遗漏了什么?

(注意:这个答案应该是一个注释,但我无法在注释中创建一个代码片段。)

const players = [
    {
        id: 0,
        name: "John",
        ready: false,
    },
    {
        id: 1,
        name: "Jack",
        ready: false,
    },
    {
        id: 2,
        name: "Eric",
        ready: false
    }
];

players.map((player, index) => {
    const readyPlayer = [];

players.forEach((item)=> {
  readyPlayer.push({
    id: item.id,
    name: item.name,
    ready: item.ready
  });
});
    // console.log(`${index}:${readyPlayer[index].test}`);
    readyPlayer[index].test = "test";
    // console.log(`${index}:${readyPlayer[index].test}`);
});

console.log(players)
© www.soinside.com 2019 - 2024. All rights reserved.