简体   繁体   中英

React onmouseenter/onmouseleave not changing state on mouse leave with immer produce function

In this codesandbox I am trying to change the background color of a div element on mouseenter and revert it on mouse leave. It only works on the outermost edge divs.

I know that setting state is "async" but the fact it does work on the outer edge makes me question it being a closure issue.

Using onMouseOut does not make a difference. I could be approaching a problem like this the wrong way completely but I cannot figure out what is wrong with the current implementation.

You need to update the state bases on previous value. That's a closure issue. You don't need to use the editGrid state. Instead use setEditGrid with produce function which will pass previous value as first argument.

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

You can just update changes in that argument (Mostly we call it as draft). You can read more passing a function in setState in React Docs

You can improve one thing in your code. You don't need to set id to each grid block. Instead use the rowIndex and colIndex if there's no such requirement that affects the grid structure.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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