web-dev-qa-db-ja.com

React.jsコンポーネントの拡張

Backbone.jsについて私が最も感謝していることの1つは、単純でエレガントな継承がどのように機能するかです。私はReactを理解し始めており、このBackboneコードに似た反応を実際に見つけることはできません

var Vehicle = Backbone.View.extend({
    methodA: function() { // ... }
    methodB: function() { // ... }
    methodC: function() { // ... }
});

var Airplane = Vehicle.extend({
    methodC: function() {
        // Overwrite methodC from super
    }
});

反応では、 ミックスインを持っている であり、これらを使用すると、このように行った場合、上記の例に多少近づくことができます

var vehicleMethods = {
    methodA: function() { // ... }
    methodB: function() { // ... }
}

var Vehicle = React.createClass({
    mixins: [vehicleMethods]
    methodC: function() { 
        // Define method C for vehicle
    }
});

var Airplane = React.createClass({
    mixins: [vehicleMethods]
    methodC: function() {
        // Define method C again for airplane
    }
});

これは同じものを何度も定義するよりも繰り返しは少なくなりますが、Backboneの方法ほど柔軟ではないようです。たとえば、ミックスインの1つに存在するメソッドを再定義/上書きしようとすると、エラーが発生します。その上、React.jsの方法は、私が書くためのより多くのコードです。

Reactには信じられないほど巧妙なものがありますが、これはReactから機能が欠落しているように感じるよりも、これを適切に行う方法を得ていない場合のほうが多いように感じます。

ポインタは大歓迎です。

67
Ahrengot

継承に似たもの(実際にはcompositionがコメントで指摘されているように)を取得するには、例のAirplaneVehicleでラップします。 VehicleコンポーネントのAirplaneのメソッドを公開する場合は、 ref を使用して、それらを1つずつ接続できます。これは正確には継承ではありません(実際にはcompositionです)、特にthis.refs.vehicleはコンポーネントがマウントされるまでアクセスできないためです。

var Vehicle = React.createClass({
    ...
});

var Airplane = React.createClass({
    methodA: function() {
      if (this.refs != null) return this.refs.vehicle.methodA();
    },
    ...
    render: function() {
        return (
            <Vehicle ref="vehicle">
                <h1>J/K I'm an airplane</h1>
            </Vehicle>
        );
    }
});

また、 Reactの公式ドキュメント では、継承よりも合成を好むことに言及する価値があります。

継承についてはどうですか? Facebookでは、数千のコンポーネントでReactを使用していますが、コンポーネントの継承階層を作成することをお勧めするユースケースは見つかりませんでした。

小道具と構成は、明示的で安全な方法でコンポーネントの外観と動作をカスタマイズするために必要なすべての柔軟性を提供します。コンポーネントは、プリミティブ値、React要素、または関数を含む任意の小道具を受け入れる場合があることに注意してください。

コンポーネント間で非UI機能を再利用する場合は、別のJavaScriptモジュールに抽出することをお勧めします。コンポーネントはそれをインポートし、拡張せずにその関数、オブジェクト、またはクラスを使用できます。

ES2015/ES6 +を使用すると、オブジェクトの小道具をAirplaneコンポーネントからVehicleコンポーネントに拡散することもできます。

render: function() {
    return (
        <Vehicle {...this.props}>
            <h1>J/K I'm an airplane</h1>
        </Vehicle>
    );
}
59
Ross Allen

プロジェクトでwebpack + babel + react NPMパッケージを使用する場合、ES6 OOP実装では、次のように簡単になります。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class BaseComponentClass extends Component {
  componentDidMount() {} 
  render() { return (<div>Base Component</div>) }
}
class InheritedComponentClass extends BaseComponentClass {
  // componentDidMount is inherited
  render() { return (<div>Inherited Component</div>) } // render is overridden 
}
ReactDOM.render(<InheritedComponentClass></InheritedComponentClass>, 
     document.getElementById('InheritedComponentClassHolder'));

注:このような設定の簡単なスターターキットは次のとおりです。 https://github.com/alicoding/react-webpack-babel

4
Ashot