Cara yang benar untuk mewarisi komponen React

Saya memahami bahwa pertanyaan saya sedikit bias, tetapi saya sangat baru dalam Javascript dan prototypes, dan saya membacanya, tetapi saya tidak begitu mengerti bagaimana menerapkan teknik itu pada masalah praktis saya. Jadi sebuah contoh akan sangat membantu. Jadi saya punya komponen React, yang pada dasarnya terlihat seperti itu:

var Component1 = React.createClass({

getInitialState: function () {
        return ({
            searchable: true,
        })
    },

function1: function () {
        return ({
            somevalue
        })
    },

render: function () {

        var redText = {
            color: 'red'
        };

        var redBorder = {
            color: 'red',
            border: '1px solid red'

        };

        return (
                <form>
                    <div>
                        <a onClick={this.props.handleAddClick}>Something</a>
                    </div>

                    <div>
                        <label>Some label</label>
                        <input type="text"/>
                    </div>
               </form> ) 
});

Saya juga memiliki Component2 yang pada dasarnya sama persis, tetapi memiliki satu <input/> tambahan di dalam return dari fungsi render-nya.

Saya juga memiliki Component3, yang memiliki fungsi yang sama, tetapi memiliki fungsi render() yang berbeda.

Lalu bagaimana cara menerapkan warisan di sini dan menghindari copy-paste 3 kali? Saya hanya melewatkan beberapa ilustrasi praktis, jadi saya akan menghargainya.

Sunting1______________________________________ Jadi saya mencoba mengimplementasikan pewarisan Prototipe sesuai jawaban pertama, tetapi tampaknya React tidak melihat fungsi-fungsi ini: getInitialState() adalah null, keadaan awal adalah null setelah rendering. Apa yang salah dengan pendekatan ini?

Saya juga mencoba mengikuti buku teks dan melakukan:

function MyPrototype() {};
MyPrototype.prototype.getInitialState = function () {
    return ({
        someProperty: true;
    })
};

function Component1() {};
Component1.prototype = Object.create(MyPrototype.prototype);
Component1.prototype.render = function () {
    console.log(this);
    return (<div></div>)};

var MyComponent1 = React.createClass(new Component1());

Namun ketika saya membuka browser, saya mendapat pesan error: Uncaught Invariant Violation: createClass(...): Class specification must implement arendermethod.

Apa yang saya lakukan salah dengan cara ini?

Sunting2________________________________________________

Sebenarnya, saya melihat bahwa React tidak mendukung mixin dan juga prototipe. Komposisi harus digunakan sebagai gantinya. Dijelaskan dalam artikel ini: Dan Artikel Abramov, Mixin Sudah Mati. Komposisi Umur Panjang


person Battle_Slug    schedule 02.05.2016    source sumber


Jawaban (1)


Di React, pewarisan komponen sangat tidak disarankan.
React jauh lebih cocok untuk mengekspresikan hubungan yang sama melalui komposisi.

Berikut adalah contoh penggunaan komposisi:

class Button extends Component {
  render() {
    return (
      <div className='Button' style={{ color: this.props.color }}>
        {this.props.children}
      </div>
    )
  }
}

class DeleteButton extends Component {
  render() {
    return (
      <Button color='red'>Delete</Button>
    )
  }
}

Perhatikan bagaimana DeleteButton menggunakan tampilan dan nuansa Button tanpa mewarisi darinya. Sebaliknya, Button mendefinisikan bagian-bagiannya yang dapat dikonfigurasi melalui props, dan DeleteButton menyediakan props tersebut. Dalam DOM sebenarnya, <Button /> dan <DeleteButton /> akan dirender ke satu node DOM—resolusi rekursif terjadi pada waktu render(), dan ini adalah ide inti React.

Faktanya, jika Anda tidak memerlukan lifecycle hook atau status lokal, Anda bahkan dapat mendefinisikan komponen sebagai fungsi:

function Button({ color, children }) {
  return (
    <div className='Button' style={{ color }}>
      {children}
    </div>
  )
}

function DeleteButton() {
  return (
    <Button color='red'>Delete</Button>
  )
}

Anda bahkan dapat menggabungkan kelas dengan fungsi. Ini tidak mungkin dilakukan dengan pewarisan, tetapi berfungsi baik dengan komposisi.

Adapun kasus penggunaan spesifik Anda:

Saya juga memiliki Component2 yang pada dasarnya sama persis, tetapi memiliki satu <input/> tambahan di dalam kembalinya fungsi rendernya.

Anda dapat meminta Component1 menerima this.props.children dan menggunakannya dalam nilai kembalian metode render(), dan membuat Component2 dirender ke <Component1><input /></Component>. Ini sangat mirip dengan apa yang saya tunjukkan di atas. Anda juga tidak harus menggunakan prop children—Anda dapat meneruskan elemen React di prop mana pun, mis. <Component1 footer={<input />} />, lalu Anda dapat menggunakan this.props.footer di dalam Component1.

Saya juga memiliki Component3, yang memiliki fungsi yang sama, tetapi memiliki fungsi render() yang berbeda.

Jika mereka berbagi kode lain (misalnya utilitas yang menghitung beberapa data), pindahkan kode tersebut di luar komponen ke dalam modul bersama, dan impor dari kedua komponen.

Jika mereka berbagi UI apa pun, ekstrak UI tersebut ke komponen lain, dan gunakan dari kedua komponen Anda.

person Dan Abramov    schedule 03.05.2016
comment
Luar biasa, Anda menjawab postingan saya :) Hari ini saya telah menemukan artikel Anda dan mendapatkan konsekuensi yang hampir sama, jadi duduk-duduk mengutak-atik komposisi malam ini, hanya memerlukan beberapa contoh praktis lagi. Terima kasih atas penjelasan ini dan atas pekerjaan Anda! Saya menggunakan Redux secara ekstensif dan saya sangat senang dengannya. - person Battle_Slug; 03.05.2016
comment
Biasanya saya mengekstrak komponen secara ekstensif, sehingga kode saya tidak mengulangi bagian render. Yang saya butuhkan sebenarnya adalah cara berbagi kode yang sama untuk getInitialState dan fungsi lain yang sama. Itulah yang saya coba sekarang. - person Battle_Slug; 03.05.2016
comment
Apa kasus penggunaan Anda untuk berbagi kode di getInitialState? - person Dan Abramov; 06.05.2016
comment
Sebenarnya, saya melakukan apa yang Anda katakan: Saya punya beberapa SharedComponent, jadi saya meneruskannya ke anak-anak dengan fungsinya sendiri. Ini berfungsi dengan baik, kodenya tidak berulang. Bersamaan dengan ini anak-anak saya memiliki beberapa bendera global di redux status toko. SharedComponent dirender bergantung pada tanda tersebut. Itu juga memilih onClick penangan apa yang akan digunakan oleh beberapa tombol berdasarkan tanda-tanda tersebut di dalam status redux. Ini cara yang benar, bukan? Kode ini tidak diulang, dan saya memiliki komposisi di sini. - person Battle_Slug; 06.05.2016