一种方法是在每次注册事件侦听器时创建一个新的去抖动函数,而不是重复使用相同的函数,在这种情况下,事件处理程序将在组件的每个实例中独立地去抖动。
const _setViewport = () => (
p: Props,
s: State,
rowHeaderObj: any,
scrollContainer: HTMLDivElement,
ref: any
) => {
// ... some code here
}
const MyComponent: React.FC<Props> = (props) => {
const [state, setState] = useState<State>()
const ref = useRef<any>()
useEffect(() => {
const srollableElement = document.querySelector(props.scrollSelector!)
if (!srollableElement) {
return
}
const setViewport = debounce(_setViewport, 20)
const scrollHandler = (e: Event) =>
setViewport(props, state, e.target as HTMLDivElement, ref)
srollableElement.addEventListener('scroll', scrollHandler, true)
return () => {
srollableElement.removeEventListener('scroll', scrollHandler, true)
}
}, [state, props, ref])
return <></>
}
附带说明,请注意useEffect 的这种用法,因为(我认为)传递给组件的props 参数会在每次父组件重新渲染时发生变化,从而导致 useEffect 可能重新经常跑。对此的一种解决方法是确保传递给useEffect 的依赖项数组仅包含原始值或稳定值。随意阅读 React 文档的 this section 以讨论该主题。考虑到这一点,您可能需要将上面的示例重写如下(取决于 Props 类型的形状):
interface Props {
scrollSelector?: string
b: string
c: number
}
const _setViewport = () => (
p: Props,
s: State,
rowHeaderObj: any,
scrollContainer: HTMLDivElement,
ref: any
) => {
// ... some code here
}
const MyComponent: React.FC<Props> = ({ scrollSelector, b, c }) => {
const [state, setState] = useState<State>()
const ref = useRef<any>()
useEffect(() => {
if (!scrollSelector) {
return
}
const srollableElement = document.querySelector(scrollSelector)
if (!srollableElement) {
return
}
const setViewport = debounce(_setViewport, 20)
const scrollHandler = (e: Event) =>
setViewport(
{ scrollSelector, b, c },
state,
e.target as HTMLDivElement,
ref
)
srollableElement.addEventListener('scroll', scrollHandler, true)
return () => {
srollableElement.removeEventListener('scroll', scrollHandler, true)
}
}, [state, scrollSelector, b, c, ref])
return <></>
}