Неожиданная мутация массива в React - PullRequest
0 голосов
/ 28 апреля 2020

Я только учусь программировать и пишу одно из моих первых приложений в 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;

Примечание: мне удалось заставить компонент действительно делать то, что предполагалось, но вышеупомянутая неожиданная мутация сохраняется и остается для меня загадкой.

1 Ответ

0 голосов
/ 28 апреля 2020

Я создал базовый c рабочий пример, используя предоставленный вами фрагмент кода. Оба оператора 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...