Reactガイドを読んでいくその52

これは

Reactのガイドを読んでいく記事です。

ガイドのリンク

ja.reactjs.org

他のライブラリとのインテグレーション

Model 層とのインテグレーション

一般的にReactのstate、Flux、Reduxのような一方向のデータフローの使用が推奨されるが、Reactコンポーネントはほかのフレームワークやライブラリのモデル層を利用することが可能。

Backbone Model からデータを抽出する

これまでのアプローチではReactコンポーネントがBackboneのモデルとコレクションを認識することが必要だった。
なのであとで別のデータ管理ソリューションに移行する場合はBackboneとのインテグレーション箇所はできるだけコードの一部に集中させるようにした方が良い。

一つの解決方法としては変更があるたびにモデルの属性をプレーンなデータとして抽出するようにして、そのロジックを一箇所だけで保持する。
こうすることで高階コンポーネントだけがBackboneモデルの内部動作について知っておく必要があり、アプリケーションの他のコンポーネントは関与しなくて済む。

こういった手法はBackboneだけに限らず、ライフサイクルメソッドで変更を購読して必要に応じてデータをローカルのReact状態にコピーすることで任意のモデルライブラリでReactを使用できる。

function connectToBackboneModel(WrappedComponent) {
  return class BackboneComponent extends React.Component {
    constructor(props) {
      super(props);
      this.state = Object.assign({}, props.model.attributes);
      this.handleChange = this.handleChange.bind(this);
    }

    componentDidMount() {
      this.props.model.on('change', this.handleChange);
    }

    componentWillReceiveProps(nextProps) {
      this.setState(Object.assign({}, nextProps.model.attributes));
      if (nextProps.model !== this.props.model) {
        this.props.model.off('change', this.handleChange);
        nextProps.model.on('change', this.handleChange);
      }
    }

    componentWillUnmount() {
      this.props.model.off('change', this.handleChange);
    }

    handleChange(model) {
      this.setState(model.changedAttributes());
    }

    render() {
      const propsExceptModel = Object.assign({}, this.props);
      delete propsExceptModel.model;
      return <WrappedComponent {...propsExceptModel} {...this.state} />;
    }
  }
}

今日はここまで。