javascript - React hooks, hammerjs with closures
问题描述
In a feature request, I needed to detect swipe events and change something on dom accordingly. So I decided to use hammerjs and give it a shot for react hooks. But I didn't understand how the closures actually work in code below. Can someone explain why left & right handlers are always using first value of state object
tl;dr: Can't change counter properly with swipes. Goes only to -1 or 1 min max
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>
);
};
Here is codesandbox https://codesandbox.io/s/l911vj98yz
解决方案
Hammer 对象的回调范围仅在第一次渲染时捕获一次。值是否更改无关紧要,范围与初始值一起保留。为避免此问题,您可以使用函数形式来更新您的值。
h.on("swipeleft", () => setCounter(previousCounter => previousCounter + 1);
推荐阅读
- javascript - JS:处理列表时的“前”和“后”操作(使用 IIFE ?)
- typescript - 如何修复错误类型错误:无法读取 null 的属性“0”?
- django - Django:在管理员中“清理”后执行的方法
- google-bigquery - 当小表包含分区列的空值时,使用分区过滤器将小表合并到大表中
- javascript - 当我已经在 catch 块中抛出错误时得到未处理的 Promise 拒绝
- visual-studio-code - 配置 VSCode 快速导航以同时列出节点模块目录中的文件?
- r - 尝试使用 iris 数据集计算 kNN
- angular - 角度推送对象到数组更新或添加新的
- python - 我尝试使用 python 进行 BTC 监控,但它不起作用
- java - 使用 DFS 检测无向图中的循环