跳至主要内容

[ReactDoc] 處理事件 Handling Events

重要觀念

Event Pooling and Synthetic Event

記得把在 event 中使用到的變數先存起來,才能避免 synthetic event 的錯誤訊息(如下):

This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See react-event-pooling for more information.

解決方式除了使用 event.persist() 之外,也可把該 event 先存成一個變數,例如:

const handleClick = (e) => {
const target = e.target; // 先把 e.target 存成一個變數
console.log(target);
};

Event Pooling @ React Docs

Code Snippets

this 的綁定

function component:無法綁定 this

// Stateless Functional Component
function ActionLink() {
// STEP 2: 定義 event handler
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}

return (
// STEP 1: 監聽事件
<a href="#" onClick={handleClick}>
Click me
</a>
);
}

**stateless function component 中的 this 會指稱到 Window**

Class component

class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };

// STEP 3: 綁定 event handler 的 this
this.handleClick = this.handleClick.bind(this);
}

// STEP 2: 定義 event handler
handleClick(e) {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
}

render() {
return (
// STEP 1: 監聽事件
<button onClick={this.handleClick}>{this.state.isToggleOn ? 'ON' : 'OFF'}</button>
);
}
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Toggle />);

Class component with Public Class Fields syntax

class LoggingButton extends React.Component {
// 如果有支援 public class fields 這種語法(實驗性)
// 可以透過這樣綁定 this
handleClick = (e) => {
console.log('this is:', this);
}

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

在事件中代入其他參數(parameters)

class Toggle extends React.Component {
constructor(props) {
super(props);

this.handleClick = this.handleClick.bind(this);
}

handleClick(id, e) {
// Do something here ...
}
}

<button onClick={(e) => this.handleClick(id, e)}>Delete Row</button>
<button onClick={this.handleClick.bind(this, id)}>Delete Row</button>
  • 使用的是箭頭函數,則代入參數的順序可以自己決定。
  • 使用的是 bind,則 event handler 的最後一個參數一定會是 event
  • 這兩種方法都不是最好的寫法,因為都會在該元件轉譯時,重複產生同樣內容的 function。
最好的寫法可以是這樣
class Toggle extends React.Component {
constructor(props) {
super(props);

this.handleClick = this.handleClick.bind(this);
}

// 可以簡寫成 handleClick = params => e => {...}
// !!下面這種寫法若沒有使用 arrow function 則 this 會變成 undefined
handleClick(params) {
return (e) => {
// Do something here ...
};
} // /handleClick
}

<button onClick={this.handleClick('params')}>Delete Row</button>;

ReactJS - Parameterized Event Handlers @ Medium

參考