项目文件夹

文件
2026-07-13 21:36:17 +08:00

56 行
1.5 KiB
Markdown

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
title: Store Event Handlers in Refs
impact: LOW
impactDescription: 稳定的订阅
tags: advanced, hooks, refs, event-handlers, optimization
---
## 将事件处理函数存储在 Refs 中
当回调函数被用于那些不应因回调变化而重新订阅的 effect 时,应将回调存储在 ref 中。
**错误做法(每次渲染都重新订阅):**
```tsx
function useWindowEvent(event: string, handler: (e) => void) {
useEffect(() => {
window.addEventListener(event, handler)
return () => window.removeEventListener(event, handler)
}, [event, handler])
}
```
**正确做法(稳定的订阅):**
```tsx
function useWindowEvent(event: string, handler: (e) => void) {
const handlerRef = useRef(handler)
useEffect(() => {
handlerRef.current = handler
}, [handler])
useEffect(() => {
const listener = (e) => handlerRef.current(e)
window.addEventListener(event, listener)
return () => window.removeEventListener(event, listener)
}, [event])
}
```
**替代方案:如果你在使用最新版 React,可以使用 `useEffectEvent`**
```tsx
import { useEffectEvent } from 'react'
function useWindowEvent(event: string, handler: (e) => void) {
const onEvent = useEffectEvent(handler)
useEffect(() => {
window.addEventListener(event, onEvent)
return () => window.removeEventListener(event, onEvent)
}, [event])
}
```
`useEffectEvent` 为同一模式提供了更简洁的 API:它创建一个稳定的函数引用,始终调用最新版本的处理函数。