簡體   English   中英

在 React 中使用鈎子創建事件處理程序的正確方法?

[英]Correct way to create event handlers using hooks in React?

在典型的基於類的 React 組件中,這是我創建事件處理程序的方式:

class MyComponent extends Component {
  handleClick = () => {
    ...
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

但是,當我使用基於鈎子的函數范式時,我發現自己有兩個選擇:

const MyComponent = () => {
  const [handleClick] = useState(() => () => {
    ...
  });

  return <button onClick={handleClick}>Click Me</button>;
};

或者:

const MyComponent = () => {
  const handleClick = useRef(() => {
    ...
  });

  return <button onClick={handleClick.current}>Click Me</button>;
};

哪一個客觀上更好,原因是什么? 有沒有我還沒有聽說過或發現的另一種(更好的)方法?

感謝您的幫助。

編輯:我在 CodeSandbox 上放了一個例子展示了這兩種方法。 從那里的代碼中可以看出,兩者似乎都沒有不必要地在每次渲染時重新創建事件處理程序,因此我認為不可能出現性能問題。

我不推薦useStateuseRef

你實際上根本不需要任何鈎子。 在許多情況下,我建議簡單地這樣做:

const MyComponent = () => {
  const handleClick = (e) => {
    //...
  }

  return <button onClick={handleClick}>Click Me</button>;
};

但是,有時建議避免在渲染函數中聲明函數(例如jsx-no-lambda tslint 規則)。 這有兩個原因:

  1. 作為性能優化,以避免聲明不必要的函數。
  2. 避免對純組件進行不必要的重新渲染。

我不會太擔心第一點:鈎子將在函數內部聲明函數,並且該成本不太可能成為您的應用程序性能的主要因素。

但是第二點有時是有效的:如果一個組件被優化(例如使用React.memo或被定義為一個PureComponent )以便它只在提供新的 props 時重新渲染,傳遞一個新的函數實例可能會導致組件重新渲染- 不必要地渲染。

為了解決這個問題,React 提供了useCallback鈎子,用於useCallback回調:

const MyComponent = () => {
    const handleClick = useCallback((e) => {
        //...
    }, [/* deps */])

    return <OptimizedButtonComponent onClick={handleClick}>Click Me</button>;
};

useCallback只會在必要時返回一個新函數(每當 deps 數組中的值發生變化時),因此OptimizedButtonComponent不會重新渲染超過必要的次數。 所以這解決了問題#2。 (請注意,它沒有解決問題 #1,每次渲染時,仍會創建一個新函數並將其傳遞給useCallback

但我只會在必要時這樣做。 您可以將每個回調包裝在useCallback ,它會起作用……但在大多數情況下,它沒有任何幫助:帶有<button>原始示例不會從記憶化回調中受益,因為<button>不是一個優化的組件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM