reactjs 用immer produce函数对鼠标进入/鼠标离开不改变状态作出React

8xiog9wr  于 2022-12-26  发布在  React
关注(0)|答案(1)|浏览(252)

在这个codesandbox中,我尝试在鼠标进入时改变一个div元素的背景色,并在鼠标离开时恢复它。它只适用于最外面的div元素。
我知道设置状态是“异步”的,但事实上它确实在外缘工作,这让我怀疑它是一个闭包问题。
使用onMouseOut并没有什么不同。我可能完全错误地处理了这样的问题,但我找不出当前实现的问题所在。

wqsoz72f

wqsoz72f1#

你需要根据先前的值更新状态。这是一个闭包问题。你不需要使用editGrid状态。而是使用setEditGrid和produce函数,该函数将先前的值作为第一个参数传递。

setEditGrid(
  produce((draft) => {
    draft[rowIndex][colIndex] = 2;
  })
);

您可以只更新参数中的更改(通常我们称之为草稿)。您可以在ReactDocs的setState中阅读更多传递函数的内容
你可以在代码中做一点改进,你不需要为每个网格块设置id,如果没有这样的要求会影响网格结构,就使用rowIndexcolIndex

import { useState, Fragment } from "react";
import produce from "immer";
const colors = ["", "#A5668B", "#FACFAD", "#F8BD7F", "#7DAF9C", "#95190C"];

export default function App() {
  const [editGrid, setEditGrid] = useState([
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  ]);

  // const [currentShip, setCurrentShip] = useState(2);

  return (
    <div className='App'>
      <div style={{ display: "grid", textAlign: "center", gridTemplateColumns: "repeat(11, minmax(10px, 50px))" }}>
        {["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"].map((letter) => {
          return (
            <div key={letter} className='p-4'>
              {letter}
            </div>
          );
        })}
        {editGrid.map((rows, rowIndex) =>
          rows.map((col, colIndex) => {
            return (
              <Fragment key={`${rowIndex}-${colIndex}`}>
                {colIndex === 0 && <div>{rowIndex + 1}</div>}
                <div
                  style={{ backgroundColor: colors[editGrid[rowIndex][colIndex]], aspectRatio: 1 / 1 }}
                  onMouseOver={(e) => {
                    setEditGrid(
                      produce((draft) => {
                        draft[rowIndex][colIndex] = 2;
                      })
                    );
                  }}
                  onMouseOut={(e) => {
                    setEditGrid(
                      produce((draft) => {
                        draft[rowIndex][colIndex] = 0;
                      })
                    );
                  }}
                >
                  {editGrid[rowIndex][colIndex]}
                </div>
              </Fragment>
            );
          })
        )}
      </div>
    </div>
  );
}

相关问题