ES6でReact使ってたらsetStateがundefinedとか怒られた件
急に寒くなってきたこの頃、いかがお過ごしでしょうか。
鼻水やらくしゃみやら頭痛やら止まらなくて調べたら「寒暖差アレルギー」なんじゃないかと思い始めました。
とっしぃです。
Uncaught TypeError: Cannot read property 'setState' of undefined
ところで、業務に関係ありそうでなさそうな適当なツールをChromeのextensionで作ってみようと思い、 どうせ外に出すわけでもないツールだし以前から興味のあったReactで書いていたわけです。
更にどうせならES6で書かない理由もないということで、
var CommentBox = React.createClass({ ...
ではなく
class CommentBox extends React.Component { ...
って感じ。
でもそこで
class CommentBox extends React.Component { constructor(props) { super(props); let data = localStorage.getItem('data_key'); this.state = { data: data } } changeData(e) { this.setState({data: e.target.value}); } save(e) { e.preventDefault(); localStorage.setItem('data_key', this.state.data); return false; } render() { <form> <Input type="text" value={this.state.data} onChange={this.changeData} label="DATA" /> <button onClick={this.save}>SAVE</button> </form> } }
的に書いてみたところ、developer toolのコンソールに
Uncaught TypeError: Cannot read property 'setState' of undefined
とか出てるじゃないですか。
色んなチュートリアル見ながらその通りやったのに(´・ω・`)
調べてみると
どうやら
var CommentBox = React.createClass({
で書いた場合はthisが勝手にbindされるけど、ES6で
class CommentBox extends React.Component {
って書いた場合はthisがbindされないとのこと。
なのでコンストラクタで明示的に
class CommentBox extends React.Component { constructor(props) { super(props); let data = localStorage.getItem('data_key'); this.state = { data: data } this.changeData = this.changeData.bind(this); this.save = this.save.bind(this); }
とbindしてあげないといけないらしい。
まとめ
Reactもbabelもちょこちょこバージョン上がってるので npm install して落ちてきたバージョンが新し目だったらちゃんとリリースノート(の翻訳でもいいので)を見といた方がいいですね。 ReactなんてrenderメソッドがReactクラスじゃなくてReactDOMクラスのメソッドになってたし。