提问人:Ikhyeon Kim 提问时间:8/7/2023 更新时间:8/11/2023 访问量:55
在 typescript React 中使用带有事件参数的闭包
Using closure with event arguments in typescript React
问:
我正在尝试使用带有打字稿 React 的闭包来实现去抖动函数。
问题是,每次我尝试传递事件参数时,它似乎都对函数进行了新的引用。所以我认为这与传球和执行有关......谁能帮我?_handleScroll
这是行不通的
const _handleScroll = (e: UIEvent<HTMLElement>): (() => void) => {
e.stopPropagation();
let prev = Date.now();
const debounce = 500; // 500ms
let counter = 0;
return () => {
const now = Date.now();
if (prev - now > debounce) {
prev = now;
setScrollHeight(e.currentTarget.scrollTop);
}
++counter;
console.log("@@@", { now, prev, counter }); // result: counter: 1, 1, 1,...
};
};
...
<div
className="h-full overflow-y-auto"
onScroll={(e) => _handleScroll(e)()}
>
...
但这有效
const _handleScroll = (): (() => void) => {
// e.stopPropagation();
let prev = Date.now();
const debounce = 500; // 500ms
let counter = 0;
return () => {
const now = Date.now();
if (prev - now > debounce) {
prev = now;
// setScrollHeight(e.currentTarget.scrollTop);
}
++counter;
console.log("@@@", { now, prev, counter }); // result: counter: 1, 2, 3,...
};
};
...
<div className="h-full overflow-y-auto" onScroll={_handleScroll()}>
...
答:
0赞
Eric Khosrafian
8/7/2023
#1
在传递句柄滚动时提供的第二个代码块中,就像传递该函数的返回值一样。
但是在你传递的第一个代码块中,你实际上是在传递该函数的引用。每次你的组件重新渲染时,传递给 div 的引用都会改变,如果你想防止 use useCallback 钩子,它类似于 useEffect,你把你的函数包装在其中,并将你的依赖项传递到 [] 中,它基本上会缓存你的函数引用,并且只在你的依赖项发生变化时才改变它
希望这会有所帮助onScroll={_handleScroll()}
onScroll={_handleScroll}
评论
0赞
Ikhyeon Kim
8/7/2023
不幸的是,使用给了我相同的结果:/useCallback
1赞
Eric Khosrafian
8/7/2023
我认为您的问题是,当此组件重新呈现时,您会丢失 scrollTop 值,对吗?如果这是您的问题,您可以将整个组件包装在 useMemo 中,我遇到了类似的问题,我正在放大图表并且父重新渲染正在重置我的缩放 useMemo 修复了它
1赞
Humanoid Mk.12
8/7/2023
#2
我想如果我了解你想要什么会很有帮助。
useRef 用于避免重新渲染。
let prev = useRef<number>();
let height = useRef<number>(0);
const _handleScroll = () => {
const now = Date.now();
const debounce = 500; // 500ms
if (!prev.current) {
++height.current;
prev.current = Date.now();
setScrollHeight(e.currentTarget.scrollTop);
}
if (!!prev.current && now - prev.current > debounce) {
prev.current = Date.now();
setScrollHeight(e.currentTarget.scrollTop);
++height.current;
}
};
<div className="h-full overflow-y-auto" onScroll={_handleScroll}>
_handleScroll将在每次滚动时激活,但状态更新了 500 毫秒。
评论
0赞
Ikhyeon Kim
8/7/2023
最初我实际使用过,正如你所写的那样,它工作正常。但我只想尝试关闭,但感谢您的帮助!useRef
useRef
评论
setHeight
500ms
debounce