React钩子,带有封闭的Hammerjs

时间:2019-01-16 11:37:25

标签: javascript reactjs react-hooks

在功能请求中,我需要检测滑动事件并相应地更改dom上的某些内容。因此,我决定使用Hammerjs并对其进行反应挂钩。 但是我不明白闭包实际上如何在下面的代码中工作。 有人可以解释为什么左右处理程序总是使用状态对象的第一个值

tl; dr:无法通过滑动正确更改计数器。最多只能达到-1或1分钟

const App = () => {
  const elm = useRef(null);
  const [counter, setCounter] = useState(0);
  const [obj, setObj] = useState({ counter: 0 });
  const [mounted, setMounted] = React.useState(false);

  React.useLayoutEffect(() => {
    if (!mounted && elm.current) {
      const h = new Hammer(elm.current);
      h.on("swipeleft", () => setCounter(counter + 1));
      h.on("swiperight", () => setCounter(counter - 1));
      h.on("swipeleft", () => setObj({ counter: obj.counter + 1 }));
      h.on("swiperight", () => setObj({ counter: obj.counter - 1 }));
      setMounted(true);
    }
  });

  return (
    <div
      ref={elm}
      style={{ width: "300px", height: "300px", backgroundColor: "orange" }}
    >
      <p>This is a swipeable content area</p>
      <p>Counter: {counter}</p>
      <p>Obj counter: {obj.counter}</p>
    </div>
  );
};

这是密码框https://codesandbox.io/s/l911vj98yz

1 个答案:

答案 0 :(得分:3)

Hammer对象的回调范围仅在第一次渲染时捕获一次。值是否更改都无关紧要,范围保留为初始值。为避免此问题,您可以使用the functional form来更新您的值。

h.on("swipeleft", () => setCounter(previousCounter => previousCounter + 1);