【问题标题】:Updating specific values of matrix useState hook state variable更新矩阵 useState 挂钩状态变量的特定值
【发布时间】:2021-11-25 07:20:45
【问题描述】:

我正在尝试更新一个 20x20 值的矩阵,每个插槽都绑定到一个 div,一旦单击一个 div,它的背景颜色应该会改变。

在不必设置整个矩阵的情况下,最好的方法是什么?

另外,为什么有些 set 方法不起作用,因为大多数这些方法都是通过互联网在示例中使用的?

import { useState } from "react";

function App() {
  const n = 20;

  // define [20][20] array with default value on each slot as { color: "red" }
  const [matrix, setMatrix] = useState(Array(n).fill(Array(n).fill({ color: "red" })))

  let updateCell = (i, j) => {
    console.log(i, j); // Works perfectly, returns i and j of the matrix slot binded to the clicked cell.

    // const mat = matrix; mat[i][j].color = "blue";                  // Doesnt work
    // setMatrix((mat) => { mat[i][j].color = "blue"; return mat; }); // Doesnt work
    // matrix[i][j].color = "blue"; setMatrix(matrix);                // Doesnt work
    // matrix[i][j].color = "blue"; setMatrix([...matrix]);           // Changes ALL squares instead of the one clicked.
    // const mat = Object.assign({}, matrix); setMatrix(mat);         // TypeError: matrix.map is not a function
  }

  return (

    <div className="container">

      {/* Renders all squares fine! */}
      {matrix.map((i, ipos) => {
        console.log(matrix.length);

        return (
          <div key={ipos} className="d-flex flex-row wrap">

            {i.map((j, jpos) => {
              console.log(i.length);
              return (

                <div
                  style={{ backgroundColor: matrix[ipos][jpos].color, minWidth: "5%", minHeight: "50px", textAlign: "center", color: "white" }}
                  key={ipos + ", " + jpos}
                  onClick={() => { updateCell(ipos, jpos) }}
                >
                  {ipos + ", " + jpos}
                </div>

              )
            })}

          </div>
        )

      })}

    </div>
  )
}

export default App;

最好的问候,谢谢。

【问题讨论】:

  • 你正在改变状态; React 不会更新组件,除非它是一个全新的矩阵数组。第四种变体也应该没有效果。第五个将矩阵从数组更改为对象,它们没有映射函数,因为它们不是数组。
  • @Chris G 我也尝试过该解决方案以及其他一些解决方案,但我找不到太多,大多数解决方案都行不通,或者如果可以,它会仅单击一个时更改所有单元格的颜色。此外,第四个变体由于某种原因改变了所有单元格的颜色,我可以肯定地说,因为我刚刚尝试过这些。不过感谢您的帮助!
  • 是的,问题是你如何填充数组。 { color: "red" } 创建一个 single 对象,并且所有数组元素都包含/指向该单个对象。更改颜色属性将对所有元素执行此操作。
  • 你需要像这样填充和映射:jsfiddle.net/85dfb3vx

标签: javascript reactjs use-state


【解决方案1】:

在这些 cmets(Chris G 和 RCC)的帮助下做出的回答:

你正在改变状态; React 不会更新组件,除非它是一个全新的矩阵数组。第四种变体也应该没有效果。第五个将矩阵从数组更改为对象,它们没有映射函数,因为它们不是数组。

您需要使用 setMatrix 函数进行更新,并且需要将新的 Array 传递给该函数(使用钩子时,始终需要是新的引用/对象)

是的,问题在于您如何填充数组。 { color: "red" } 创建单个对象,所有数组元素都包含/指向该单个对象。更改颜色属性将对所有元素执行此操作。

  useEffect(() => {
    const n = 20;

    for (let i = 0; i < n; i++) {
      matrix[i] = [];
      for (let j = 0; j < n; j++) {
        matrix[i][j] = { color: "red", coords: [i, j] }
      }
    }

    setMatrix([...matrix]);

  }, [])

  let updateCell = (i, j) => {
    console.log(i, j);
    matrix[i][j].color = "blue";
    setMatrix([...matrix]);
  }

【讨论】:

    【解决方案2】:

    您需要使用setMatrix 函数进行更新,并且需要将一个新数组传递给该函数(使用钩子时,始终需要是一个新的引用/对象)

    const updateCell = (i, j) => {
      let newMatrix = matrix.slice(); // just to create a copy of the matrix
      newMatrix[i][j].color = "blue";
      setMatrix( newMatrix ); // this call will trigger a new draw
    }
    

    编辑:
    此外,Array(n).fill 将在矩阵的每个位置放置相同的引用,因此更改一个值将更新所有的然后(因为所有都是相同的值/引用)

    换行

    useState(Array(n).fill(Array(n).fill({ color: "red" })))
    

    到:

    useState( Array.from({ length: 20 }, () => Array.from({length: 20}, () => ({ color: 'red' })) ) )
    

    【讨论】:

    • 您好,谢谢!我不知道,但由于某种原因,所有单元格都变成了蓝色,而不仅仅是矩阵槽值发生变化的那个。
    • 你是对的,这是因为所有的矩阵值都是相同的引用,尝试在useState上使用Array.from({ length: 20 }, () =&gt; Array.from({length: 20}, () =&gt; ({ color: 'red' })) )
    猜你喜欢
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 2021-01-27
    • 2021-10-02
    • 2020-08-20
    • 2019-08-16
    • 2021-04-10
    相关资源
    最近更新 更多