react.jsをes6で書くときのメモ

React.jsはEcmaScript 6の記法で記述できます。ES6はより直感的な記法や明確なスコープなど、多くのメリットがありますが、React.jsで使うとちょっとした不便やノウハウが必要です。これはそのときのメモです。

## イベントのコールバックのthis

次のようなコードがあります


```jsx:my-component.jsx
class MyComponent extends React.Component {
    doSomeMethod() {
       // do something
    }

   handleClick(e) {
       this.doSomeMethod();
   }

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

このコードでボタンが押されたときに呼び出されるhandleClickのthisは、イベントの呼び出し元のオブジェクト(RaisedButton)になっています。このへんのスコープの感覚はES6と違うような…。

thisがMyComponentを指すようにするには、次のようにbindします。

```jsx
return <RaisedButton onClick={this.handleClick.bind(this)}>button</RaisedButton>;
```

これで、イベントの発火時に呼び出されるhandleClickのthisはMyComponentのオブジェクトになります。

## getInitialStateが使えない

以前の記述だと

```js
var MyComponent = React.createClass({
    getInitialState: function() {
        return {key1: 1, key2: 2};
    },
    render: function() {
        return <RaisedButton>{this.state.key1}</RaisedButton>;
    }
});
```

のように記述してstateの初期値を設定していました。ES6の記法で書くと、getInitialStateは呼ばれません。stateの初期化はコンストラクタで行います。

```jsx
class MyComponent extends React.Component {
    constructor() {
        super();
        this.state = {key1: 1, key2: 2};
    }

    render() {
        return <RaisedButton>{this.state.key1}</RaisedButton>;
    }
}
```
こちらのほうがより直感的ですね。
propsのデフォルト値の設定はもっと複雑らしいですが、まだ、試していません。


## mixin

ES6ではmixinが使えなくなってしまいました。今のプロジェクトではReact Routerを使っていますが、transitionToのようなメソッドはNavigationをmixinすることを前提にしています。これ以外にもmixinを前提としているものがいくつかあり、使えないと不便です。
[Rect Mixin](https://github.com/brigand/react-mixin)はこの問題を解決してくれます。ただし、このプロダクトはホームページ上で

> I can't think of a more elegant solution to mixins in es6 classes. If someone comes up with one, create an issue and I'll link to it here.
> 
> In the future people will likely use high order components instead of mixins, making this library obsolete.
> 
> Should you use es6 classes for react components? Based on the hacks required above, I'd probably avoid it. It's important that react makes it an option, and it's important to be able to use mixins with them, which is why this library exists.

と言っているようにmixinを暫定的に使うためのもので、将来は別の仕組みにおきかえられるべきものかもしれません。
mixinは次のようにりようします。

```jsx
import React from 'react';
import ReactMixin from 'react-mixin';
import {Navigation} from 'react-router';

class MyComponent extends React.Component {
    handleClick(e) {
        this.transtionTo("someRouteObj");
    }

    render() {
        return <RaisedButton onClick={this.handleClick.bind(this)>Button</RaisedButton>;
    }
}
ReactMixin.onClass(MyComponent, Navigation);
```

これでNavigationをmixinできました。

## willTransitionToなど

RouterでonEnterを使おうとしたら動きません。コードをみると次のようになっていて、onEnterはどのようにセットすべきものなかわかりません。

```js
if (handler) {
    props.onEnter = handler.willTransitionTo;
    props.onLeave = handler.willTransitionFrom;
}
```

handlerのwillTransitionToを記述すれば目的の動作を達成できそうです。


```jsx
class MyComponent extends React.Component {
    static willTransitionTo(transition) {
        if (this.state.someState) {
            transition.redirect("/");
        }
    }

    render() {
        return <RaisedButton>Button</RaisedButton>;
    }
}
```

classのメソッドないと動いてくれないので注意します。
主に認証が必要なページなどで遷移前に状態をチェックして、ログインページを表示するとかできます。本当はRouterで設定したかったんですけど…。

## まとめ

現状、ReactをES6で記述するのは茨の道かもしれません。本当のサンプルコードもそのままでは動かないですし。
けれどもES6のわかりやすさはそのデメリットを差し引いても十分価値があるものです。JavaScriptが嫌いな私でも、この記法、わかりやすさであれば、フロントエンドの開発も苦ではなくなりそうです。