React報錯之Expected `onClick` listener to be a function

  • 2022 年 8 月 17 日
  • 筆記

正文從這開始~

總覽

當我們為元素的onClick屬性傳遞一個值,但是該值卻不是函數時,會產生”Expected onClick listener to be a function”報錯。為了解決該報錯,請確保只為元素的onClick屬性傳遞函數。

expected-onclick-listener-to-be-function.png

這裡有個例子來展示錯誤是如何發生的。

// App.js
const App = () => {
  // ⛔️ Warning: Expected `onClick` listener to be a function
  // instead got a value of `string` type.
  return (
    <div>
      <button onClick="console.log('Click')">Click</button>
    </div>
  );
};

export default App;

當按鈕的onClick屬性的期望值是函數時,我們為其傳遞了一個字符串,從而導致了錯誤的產生。

傳遞函數

為了解決該報錯,請確保只為元素的onClick屬性傳遞函數。

// App.js
const App = () => {
  const handleClick = () => {
    console.log('button clicked');
  };

  return (
    <div>
      <button onClick={handleClick}>Click</button>
    </div>
  );
};

export default App;

我們向元素的onClick屬性傳遞了一個函數,順利的解決了這個錯誤。然而,注意到我們在向onClick屬性傳遞函數時並沒有調用該函數。

我們傳遞了函數的引用,而不是函數調用的結果。

如果傳遞了函數調用的結果,那麼事件處理器將在頁面加載時立即被調用,這不是我們想要的。

傳遞參數

你通常需要做的事情是向事件處理器傳遞一個參數。你可以通過使用一個內聯箭頭函數來做到這一點。

// App.js
import {useState} from 'react';

const App = () => {
  const [count, setCount] = useState(0);

  const handleClick = (event, num) => {
    console.log(event.target);
    console.log('button clicked');
    setCount(count + num);
  };

  return (
    <div>
      <h2>{count}</h2>
      <button onClick={event => handleClick(event, 100)}>Click</button>
    </div>
  );
};

export default App;

handleClick函數是用event對象和一個數字參數調用的。需要注意的是,我們沒有向onClick屬性傳遞調用handleClick函數的結果。

我們實際上是將一個函數傳遞給它,該函數以event對象為參數,並返回以event和數字100為參數的handleClick函數的調用結果。

onclick-listener-function.gif

不要把調用handleClick函數的結果傳遞給onClick屬性,這是非常重要的。因為如若這樣的話,當頁面加載時,該函數會被立即調用,這可能會導致無限的重新渲染循環。