useState 钩子的意外行为

IT技术 reactjs use-state
2021-05-09 03:08:13

我正在尝试一个图像映射库,发现了一个意外的行为。处理函数的handleInc行为取决于它是由+按钮触发还是通过单击图像中的突出显示区域(需要移动鼠标以显示突出显示区域)。

使用+按钮时,行为与预期一致,但单击图像中突出显示的区域时,状态变量count似乎没有超出1

相同功能背后handleInc表现不同的原因是什么

这是代码(下面代码的沙箱

import { useState } from "react";
import "./styles.css";
// https://github.com/img-mapper/react-img-mapper
import ImageMapper from "react-img-mapper";

const URL =
  "https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg";

export default function App() {
  const [count, setCount] = useState(0);
  const handleInc = () => {
    // this print expected value when + button is clicked
    // but print 0 if highlighted area is clicked
    console.log(count);
    setCount(count + 1);
  };
  const handleDec = () => {
    console.log(count);
    setCount(count - 1);
  };
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={handleInc}>+</button>
      {count}
      <button onClick={handleDec}>-</button>

      <ImageMapper
        src={URL}
        map={{
          name: "asdf",
          areas: [
            {
              id: 0,
              active: true,
              title: "BB(1-4)",
              shape: "poly",
              name: "BB(1-4)",
              fillColor: "#eab54d4d",
              strokeColor: "black",
              coords: [
                260,
                142,
                77,
                196,
                184,
                530,
                840,
                529,
                928,
                283,
                894,
                26,
                389,
                53,
                343,
                31,
                321,
                90
              ]
            }
          ]
        }}
        stayMultiHighlighted
        onClick={handleInc}
      />
    </div>
  );
}
2个回答

似乎该ImageMapper组件正在记忆回调,换句话说,它已经关闭了初始count状态值,并且从那时起永远不会更新。

如果您使用功能状态更新,则单击突出显示的区域似乎可以正常工作。功能状态更新的工作方式是从前一个状态更新,而不是从回调入队的渲染周期中更新状态。

const handleInc = () => {
  setCount(count => count + 1);
};

const handleDec = () => {
  setCount(count => count - 1);
};

演示

编辑意外的使用状态钩子行为

ImageMapper确实被记住了Drew 的方法是正确的,当状态更新取决于其先前的 value 时调用setState钩子回调的推荐做法

或者,ImageMapper组件的接口有一个rerenderProps属性,您可以指定将onClick添加到其敏感度列表并覆盖记忆化:

<ImageMapper
  ...
  onClick={handleInc}
  rendererProps={['onClick']}
/>