简体   繁体   English

React中数组的意外突变

[英]Unexpected mutation of array in React

I am just learning to program and am writing one of my first applications in React.我刚刚学习编程,并且正在用 React 编写我的第一个应用程序。 I am having trouble with an unexpected mutation that I cannot find the roots of.我遇到了一个我无法找到根源的意外突变。 The snippet is part of a functional component and is as follows:该片段是功能组件的一部分,如下所示:

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>
    )
  })

Now the problem is that readyPlayer seems to be mutated before it is supposed to.现在的问题是 readyPlayer 似乎在它应该发生之前就已经发生了变异。 Both console.log's read the same exact thing.两个console.log 都读取相同的内容。 That is the array with the object inside having the test key as "test".也就是内部有 object 的数组,测试键为“test”。 forEach does not mutate the original array, and all the key values, that is id, name and ready, are primitives being either boolean or string. forEach 不会改变原始数组,所有键值,即 id、name 和 ready,都是原语,即 boolean 或字符串。 I am also not implementing any asynchronous actions here, so why do I get such an output?我这里也没有实现任何异步操作,那为什么我会得到这样的 output? Any help would be greatly appreciated.任何帮助将不胜感激。

Below is the entire component for reference in its original composition ( here also the test key is replaced with the actual key I was needing, but the problem persists either way.下面是整个组件的原始组合供参考(这里的测试密钥也被替换为我需要的实际密钥,但问题仍然存在。

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;

Note: I did manage to make the component actually do what it is supposed, but the aforementioned unexpected mutation persists and is still a mystery to me.注意:我确实设法让组件真正做到了它应该做的事情,但是前面提到的意外突变仍然存在,对我来说仍然是一个谜。

I have created a basic working example using the code snippet you provided.我使用您提供的代码片段创建了一个基本的工作示例。 Both console.log statements return a different value here.两个console.log语句在此处返回不同的值。 The first one returns readyPlayer.test as undefined , the second one as "test" .第一个返回readyPlayer.testundefined ,第二个返回为"test" Are you certain that the issue happens within your code snippet?您确定问题发生在您的代码片段中吗? Or am I missing something?还是我错过了什么?

(Note: This answer should be a comment, but I am unable to create a code snippet in comments.) (注意:这个答案应该是评论,但我无法在评论中创建代码片段。)

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM