React 與 bind this 的一些心得
我們都知道在撰寫 React class 的時候常常需要使用 bind(this)
這行語法來讓property與 this 保持關係。
於是我開始動手做點實驗,寫一支簡單的 JS 程式來探討 class 內部 property 能不能呼叫 this
。
class Animal {
constructor(name) {
this.name = name;
}
run() {
console.log(`${this.name} has run 100 cm`);
}
}
const dog = new Animal('poke');
dog.run();
這時候我們會得到輸出是
poke has run 100 cm
我們寫了一個 ES6 的 class 可以在裡面取得 this
,但是為什麼 React 內部的 property 確不能夠取得 this 呢?
我查了一些網路上的文章
當使用 extend React.Component
的方式去宣告元件的時候,React 確實會綁定 this
到元件內,但是卻有以下特定的地方才會被綁進去
- 生命周期函式,例如
componentDidMount
等等 render
內
其他自己定義的 property 就不會被綁入 this
,而且 this
會被指到 windows
這個全域上。
提供5個解法
這5個解法可以挑一種使用就可以,每一種都有不同的優缺點,大家可以依照自己使用的情境來挑選。喜歡看原文的可以點下面的連結
- 不要用 class 建構React元件的方式,改用
Rreact.createClass
我不建議使用這種方式,因為現在幾乎都是用 ES6 來寫,別自廢武功阿….
2. 在 render 內綁定 this
<Input onChange={this.handleChange.bind(this)} />
其實我也不建議用這種方式,據說會有效能的影響
3. 在 constructor
裡面綁定
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
這是很常見的方法,缺點就是要寫多一點點的程式,因為你每次做一個property function 都要 bind 一次。
4. 使用箭頭函式在 render 內
<Input onChange={(e) => this.handleChange(e)} />
據說也是有效能的 issue ,各位也可以斟酌使用
5. 在宣告 property 的時候就使用箭頭函數
handleChange = (e) => {
this.XXXX
}
在上面這麼多解法,這個應該算是比較好的解法,不用多寫一行程式去綁定,也不用在 render 裡面綁定降低效能。
總結
在了解了 React 這麼多種綁定 this 的方法之後,應該也會跟我一樣選擇使用箭頭函數來宣告 property 吧!!不過在使用箭頭函數之前必須要開啟 babel 的 transform-class-properties or enable stage-2 in Babel 這兩個功能,所以如果不太會設定 webpack 或是 babel 的同學可以建議直接用我們做好的 startKit 直接使用,裡面就已經有箭頭函數的功能了!