読者です 読者をやめる 読者になる 読者になる

ReactのES6-classが所詮糖衣構文しかも甘くない

承前:昨日の追記)

react-mixin(https://github.com/brigand/react-mixin)でES6のclass構文を試してみました。書いてから気がついたのは、短時間で試したぐらいの中ではちょっとコード書き直すだけでどんどん筋が悪い体裁になっていくので、時期尚早というか私にはまだ無理ゲー。もうチョイ調査が必要。

  • propTypesの宣言がclassブロック外に記述
  • getDefaultPropsの対応がclassブロック外に記述
  • mixinの対応でreact-mixinを使ってみたけど。。。
    • このためにreact-mixinのrequire、まあこれは些細なこと
    • classブロック外でのmixin作業
    • MixinメソッドがAutoBindingが無いために各所でbind(this)を書かなくちゃいけない。これがヘビー
    • mixinはReactコンポーネントじゃなくてDuck-Typingなピュアオブジェクトなので、class構文的な書き方はできない
  • contextTypesの宣言はどうするのかわからず、contextがきっちり動く書き方が発見できなかった

無理にclass構文を使うのはやはりやめたほうが良いのだろうか。サンプルでよく見るようなシンプルなものだったら綺麗に書けるけど。。。どうせ今はbabelでトランスパイルするので所詮糖衣構文しかも甘くない!ってんで確信なければハマる必要がないかなあ。

一方で、mixinをラッパーコンポーネントのイディオムで書き直した方は筋が良いように思いました。今までのMixinの書き方から直して下記の感じかな。MixinをReactコンポーネントを返す関数にしてみました。クロージャーで引数コンポーネントを持ち回るのは、react-side-effectのソース見て学んだ。

function WrapByMixBar(WrappedComponent) {
    return React.createClass({
        displayName: "Bar$" + WrappedComponent.displayName, // Babelが自動で書き出さない
        getDefaultProps() {
            return {fromMixBar: "Bar"};
        },
        render() {
            return <WrappedComponent {...this.props}/>;
        }
    });
}
const Foo = WrapByMixBar(React.createClass({
    displayName: "Foo", // Babelが自動で書き出さない
    render() {
        return <div>Foo {this.props.fromMixBar}</div>;
    }
}));

console.log(ReactDOMServer.renderToStaticMarkup(<Foo/>));

より直感的?Mixinもちゃんとした(Duck-Typingではない)Reactコンポーネントになったので、クライアントサイドレンダリングだったらChromeデベロッパツールのReactプラグインで中身見た時にきちんと層状に表示されます。コアとアスペクトが分離表示されてこちらが旧来より正しいように思う。その際にはBabelが対応しきれないdisplayNameを工夫しておくと吉。

追記

contextもなんか勘違いしていたみたいで、改めて書き下ろしてみたらES6-classでサクッと動いた!

class PutContext extends React.Component {
    getChildContext() {
        return {color: "#03a9f4"};
    }
    render() {
        return <div>{this.props.children}</div>;
    }
}
// propTypesと同じスタイルの設定
PutContext.childContextTypes = {color: React.PropTypes.string};

class GetContext extends React.Component {
    render() {
        const color = this.context.color;
        return <div style={{color: color}}>the context color is {color}.</div>;
    }
}
// propTypesと同じスタイルの設定
GetContext.contextTypes = {color: React.PropTypes.string}

Mixinも先のやり方で移行して、contextもOKとなると、記事タイトルから一転してES6-classで良くなったかも。