Почему мой массив не копируется без ссылки в React? - PullRequest
0 голосов
/ 08 января 2020

Я делаю веб-приложение для визуализации алгоритмов поиска путей с использованием реакции. В настоящее время у меня реализован алгоритм Дейкстры. Однако, когда я передал копию моего начального массива в мой алгоритм поиска пути, исходный массив был изменен.

import React, { useState } from "react";
import Node from "./Node";
import dijkstras from "../algorithms/dijkstras";

const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 10;
const FINISH_NODE_COL = 35;

const getGrid = () => {
  const grid = [];
  for (let row = 0; row < 20; row++) {
    const currentRow = [];
    for (let col = 0; col < 50; col++) {
      currentRow.push(createNode(col, row));
    }
    grid.push(currentRow);
  }
  return grid;
};

const createNode = (col, row) => {
  return {
    col,
    row,
    isStart: row === START_NODE_ROW && col === START_NODE_COL,
    isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
    distance: Infinity,
    isVisited: false,
    isWall: false,
    previousNode: null
  };
};

const Pathfinder = () => {
  const initialGrid = getGrid();
  const [grid, setGrid] = useState([...initialGrid]);

  const animatePath = visitedNodesInOrder => {
    for (let i = 0; i < visitedNodesInOrder.length; i++) {
      setTimeout(() => {
        const node = visitedNodesInOrder[i];
        const newGrid = grid.slice();
        const newNode = {
          ...node,
          isVisited: true
        };
        newGrid[node.row][node.col] = newNode;
        setGrid(newGrid);
      }, 100 * i);
    }
  };

  const visualizeDijkstras = () => {
    const tempGrid = [...grid];
    const startNode = tempGrid[START_NODE_ROW][START_NODE_COL];
    const finishNode = tempGrid[FINISH_NODE_ROW][FINISH_NODE_COL];
    const visitedNodesInOrder = dijkstras(tempGrid, startNode, finishNode);
    animatePath(visitedNodesInOrder);
  };

  return (
    <>
      <button onClick={() => visualizeDijkstras()}></button>
      <div className="grid">
        {grid.map((row, rowIndex) => {
          return (
            <div key={rowIndex}>
              {row.map((node, nodeIndex) => {
                const { isStart, isFinish, isVisited } = node;
                return (
                  <Node
                    key={nodeIndex}
                    isStart={isStart}
                    isFinish={isFinish}
                    isVisited={isVisited}
                  />
                );
              })}
            </div>
          );
        })}
      </div>
    </>
  );
};

export default Pathfinder;

В настоящее время все узлы настроены на посещение на первой итерации метода animatePath (), поскольку узлы в исходном массиве сетки уже отмечены как посещенные методом dijkstras. Несмотря на то, что я скопировал исходный массив во временный массив и передал его методу поиска пути.

1 Ответ

2 голосов
/ 08 января 2020

Как указано в моем комментарии, проблема в том, что ваш скопированный массив имеет вложенные массивы, которые указывают на их исходные ссылки. Поэтому, когда вы создаете новый массив, подобный этому ...grid, вы создаете новый массив со ссылками на исходные вложенные массивы.

Решение также заключается в создании новых вложенных массивов.

Если массив всего 2, вы можете сделать что-то вроде этого:

const tempGrid = [...grid.map.(subArray => [...subArray])];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...