React: Alat peraga default dalam sintaks kelas ES6

Dibuat pada 22 Apr 2015  ·  40Komentar  ·  Sumber: facebook/react

Pengumuman dukungan ES6 mengatakan:

cara idiomatis untuk menentukan status kelas adalah dengan hanya menggunakan properti instance sederhana. Demikian juga getDefaultProps dan propTypes sebenarnya hanyalah properti pada konstruktor.

Ini sangat masuk akal bagi saya, tetapi saya melihat beberapa inkonsistensi kecil yang mungkin perlu dipikirkan kembali.

Saat menggunakan sintaks .createClass , nilai yang dikembalikan oleh getDefaultProps tampaknya digunakan di titik lain dalam siklus hidup komponen -- bukan hanya di konstruktor. Misalnya, jika saya memeriksa apa yang dikirim ke componentWillReceiveProps(props) , saya dapat melihat bahwa props default diterapkan.

Ini _doesn't_ tampaknya menjadi kasus ketika menggunakan sintaks kelas ES6, yang berarti saya harus menggandakan kode. Berikut ini contoh yang saya maksud:

class Control extends React.Component {

  constructor(props) {
    props.value = props.value || '';
    super(props);
  }

  // ...

  componentWillReceiveProps(props) {
    props.value = props.value || '';
    // Do something with props...
  }

}

Seperti yang Anda lihat, saya menduplikasi ekspresi props.value = props.value || '' . Jika saya memiliki lebih dari satu default, saya jelas akan memiliki lebih banyak duplikasi.

Saat menggunakan metode .createClass , saya dapat mengembalikan {value: ''} dari metode getDefaultProps , dan ini akan berhasil, dan saya hanya perlu melakukannya sekali.

Apakah masuk akal untuk mengembalikan metode ini untuk menghindari duplikasi yang tidak perlu? Apakah ada pendekatan lain yang lebih mirip Bereaksi yang tidak saya sadari?

Komentar yang paling membantu

Itu benar. Sebagai gantinya, Anda menulis ini:

class Control extends React.Component {

  // ...

  componentWillReceiveProps(props) {
    // Do something with props...
  }

}
Control.defaultProps = {value: ''};

Apakah itu berhasil untuk Anda?

Semua 40 komentar

Alat peraga default harus sudah digabungkan saat componentWillReceiveProps dipanggil.

Alat peraga default harus sudah digabungkan saat componentWillReceiveProps dipanggil.

Sejauh yang saya tahu, getDefaultProps tidak pernah dipanggil saat menggunakan sintaks kelas ES6.

Itu benar. Sebagai gantinya, Anda menulis ini:

class Control extends React.Component {

  // ...

  componentWillReceiveProps(props) {
    // Do something with props...
  }

}
Control.defaultProps = {value: ''};

Apakah itu berhasil untuk Anda?

Ahh, maaf, saya melihatnya di dokumentasi sekarang. Terima kasih!

Karena saya mendarat di sini dari pencarian Google, dan saya lebih suka class untuk merangkum kode saya, props default dapat diatur menggunakan properti yang dihitung seperti:

import React, {Component, PropTypes} from 'react'
class DefaultPropsExample extends Component {
  static defaultProps = {
    ...Component.defaultProps,
    instructions: 'Usage instructions not provided.',
  }
}

@jhabdas Apa yang Anda berikan bukan sintaks ES2015, saya kira; Babel melempar token yang tidak terduga jika saya menggunakan alat peraga statis, namun, untuk orang-orang yang bekerja seperti saya di es2015, inilah hal yang berfungsi.

import React from 'react';
export default class extends React.Component {

  static get defaultProps() {
    return {
      // stuff you want :)
    }
  }

}

memperbarui

Setelah menginstal tautan @zpao , saya dapat menggunakan properti statis ...

@ Gopikrishna19 Anda harus mengaktifkan plugin babel lain yang mengimplementasikan proposal properti kelas: http://babeljs.io/docs/plugins/transform-class-properties/

@zpao Ooh! Hal baru lainnya hari ini :) akan mencobanya, terima kasih banyak!

@ Gopikrishna19 Saya sebenarnya menyukai cuplikan kode yang Anda posting b/c Saya dapat melakukan beberapa pra-pemrosesan sebelum menginisialisasi alat peraga default. Terima kasih telah menyebutkannya.

Ini sepertinya berhasil dan menurut saya lebih elegan:

....

 static defaultProps = {
      //someDefaultProps
  };

  constructor(props, defaultProps) {
    super(props, defaultProps);
  }

....

@fxhereng Argumen kedua dicadangkan untuk context jadi saya akan menghindari menimpanya dengan beberapa arti khusus karena ini mungkin rusak di rilis mendatang.

Ok @gaearon Apa cara terbaik untuk mengatur alat peraga default untuk Anda?

Terima kasih,

Apa cara yang disarankan untuk ini?

Jika Anda menggunakan transformasi eksperimental http://babeljs.io/docs/plugins/transform-class-properties/ , maka Anda bisa menggunakan static defaultProps = {...}; . Tidak perlu mengubah konstruktor. Jika tidak, Anda perlu menetapkan di luar:

class X extends React.Component {
}
X.defaultProps = {...};

Juga..

class X extends React.Component {
  props = {
    ...
  }
}

@efernandesng Ini bukan pola yang didukung. Itu tidak akan berperilaku seperti defaultProps dan bermutasi this.props yang seharusnya tidak Anda lakukan.

Sepertinya saya tidak bisa mendapatkan defaultProps untuk dipakai dengan kelas induk sehingga saya dapat meneruskan alat peraga itu ke kelas anak lain di dalamnya.

Apakah ada cara es6 standar untuk melakukan itu? Semua metode di sini tidak bekerja untuk saya.

Sepertinya saya tidak bisa mendapatkan defaultProps untuk dipakai dengan kelas induk sehingga saya dapat meneruskan alat peraga itu ke kelas anak lain di dalamnya.

Saya tidak mengerti apa yang Anda maksud. Bisakah Anda menunjukkan contoh?

Tentu saja, maaf tentang itu.

Berikut adalah komponennya:

import React, 
{
  Component,
  PropTypes
}                     from 'react';
import { TimerView }  from './TimerView'

class Timer extends Component {
  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(props) {
    console.log('Will receive props')
  }

  render() {
    console.log("Timer loaded")

    return (
      <TimerView {...props} />
    )
  }
}

Timer.propTypes = {
  status: PropTypes.string.isRequired,
};

Timer.defaultProps = {
  status: "This is the Timer",
};

export default Timer;

Ketika saya menjalankan webpack-dev-server, saya mendapatkan kesalahan ini:
Uncaught ReferenceError: props is not defined

Pasti ada sesuatu yang saya lakukan salah ...

props adalah variabel tidak terikat dalam metode render() . Seharusnya <TimerView {...this.props} /> .

Astaga.
Aku benar-benar merindukan yang satu ini. Saya kira karena saya menggunakan komponen stateless sebanyak kelas, saya menjadi bingung dengan yang satu ini.

Terima kasih Pak.

tidak masalah @jeanmichelcote! itu terjadi :)

Mengakses props lain untuk mendefinisikan defaultProps dianggap sebagai anti-pola?

class Comp extends from React.Component {
  static propTypes: {
    num: React.PropTypes.number.isRequired,
    action: React.PropTypes.func,
  };

  static defaultProps: {
    action: () => console.log(this.props.num), // "this" is invalid in static context
  };

  render() {
    return (
      <button onClick={this.props.action}>
        {`Log #${this.props.num}`}
      </button>
    );
  }
}

@romulof sepertinya Anda mencoba mereferensikan variabel instan dari metode statis. Anda tidak dapat melakukannya karena tidak ada cara untuk mengetahui this Anda bicarakan. Menurut definisi, hal-hal statis selalu hidup di luar konteks sebuah instance.

@romulof Itu umum dengan semua bahasa berorientasi objek. Sintaks panah gemuk mengikat ke konteks yang didefinisikan. Mungkin Anda bisa mencoba menggunakan

static defaultProps: {
    action: function() {
        console.log(this.props.num), // "this" depends on the context where it is run
    }
};

@sbussard : Tepat sekali.

Pertanyaan saya adalah tentang defaultProps diimplementasikan sebagai objek statis.
Mungkin membiarkannya menjadi fungsi, dipanggil oleh konstruktor.

Itu sengaja di luar kelas sehingga kompiler yang mengoptimalkan dapat memasukkannya ke situs panggilan.

Jadi apa jawaban akhirnya?

@gaearon Anda telah menyebutkan itu

Itu sengaja di luar kelas sehingga kompiler yang mengoptimalkan dapat memasukkannya ke situs panggilan.

tetapi apakah itu berarti tidak dapat dioptimalkan saat menggunakan "bidang instance kelas" dan/atau "bidang statis kelas"? Saya kira saya mencoba memahami pendekatan mana yang lebih disukai dan mengapa.

Jadi apa jawaban akhirnya?

Jika Anda ingin tetap menggunakan ES6, tetapkan di bagian bawah:

class MyComponent extends Component { /* ... */ }
MyComponent.defaultProps = { /* ... */ };

Jika Anda menggunakan Create React App, atau jika Anda merasa nyaman dengan sintaks eksperimental dan telah mengaktifkan transformasi properti kelas , Anda dapat melakukan ini:

class MyComponent extends Component {
  static defaultProps = { /* ... */ };
  /* ... */
}

Pendekatan ini benar-benar setara. Perhatikan bahwa jika Anda juga menggunakan dekorator, Anda mungkin memiliki bug aneh yang menggabungkan transformasi ini. Jadi saya tidak merekomendasikan menggunakan dekorator bersama dengan properti kelas.

Saya harap ini membantu!

tetapi apakah itu berarti tidak dapat dioptimalkan saat menggunakan "bidang instance kelas" dan/atau "bidang statis kelas"? Saya kira saya mencoba memahami pendekatan mana yang lebih disukai dan mengapa.

Tidak ada perbedaan antara menugaskan di akhir dan menggunakan properti kelas. Properti kelas sesuai dengan tugas. Silakan gunakan REPL di situs web Babel untuk memeriksa kode apa yang dikompilasi.

Saya ingin tahu tentang masalah yang sama yang dibicarakan @romulof . Tentu, saya dapat menggunakan static defaultProps untuk mendefinisikan properti default tetapi bagaimana jika saya ingin menggunakan konteksnya?

Mengapa ini berguna?

Saya memiliki komponen modal generik yang memiliki title dan onSubmit props. Terkadang saya ingin menggunakan Modal dengan alat peraga yang sama tetapi dari bagian yang sama sekali berbeda dari Aplikasi saya. Untuk title ini berfungsi dengan baik.

class CreateUserModal extends Modal {
  static defaultProps = { title: 'Create a new user' }
}

Namun penangan onSubmit , yang merupakan potongan kode yang layak, memerlukan konteks karena menggunakan prop yang diisi dari menghubungkan redux. Saat ini tidak ada cara bagi saya untuk mengabstraksi kode ini karena konteks tidak dapat digunakan untuk mengatur properti dari kelas induk.

Apa yang saya coba lakukan sebenarnya bukan anti pola (atau setidaknya menurut saya bukan) jadi saya ingin tahu apakah ada cara lain untuk melakukan ini?

Saya berharap saya akan dapat melakukan sesuatu seperti

class CreateUserModal extends Modal {
  constructor (props) {
    super({
      title: 'Create a new user',
      onSubmit: () => {
        // do a load of stuff using props
      }
    })
  }
}

tapi itu tidak berhasil.

@roberttod apakah Anda menemukan solusi untuk masalah Anda? Terima kasih

Saya ingin mengajukan pertanyaan lanjutan,
jika saya menggunakan aplikasi buat reaksi (skrip reaksi v1.0.12), apakah boleh mendefinisikan status awal sebagai

class Foo extends Component {
  static defaultProps = {};

  static propTypes = {};

  state = {...};
}

apa perbedaannya dibandingkan dengan menggunakan konstruktor untuk mendefinisikan status awal sebagai:

class Foo extends Component {
  static defaultProps = {};

  static propTypes = {};

  constructor(props) {
    super(props);

    this.state = {...};
  }
}

secara khusus apakah ada implikasi kinerja dalam pendekatan pertama?

Itu sama persis, tidak ada perbedaan.

@jhabdas Nah, jadi ketika defaultProps didefinisikan sebagai:

static defaultProps = {
}

Cara mengaksesnya dari metode kelas karena:

this.defaultProps

mengembalikan undefined

@majioa Saya tidak tahu tentang API tingkat kelas itu, tetapi satu ide adalah untuk men-cache alat peraga default sebagai objek terpisah dan merujuknya. Bagaimana menurutmu?

@majioa

class Foo extends React.Component {
  static defaultProps = { param: 1 };
  render() {
    return Foo.defaultProps.param;
  }
}

Saya menemui masalah yang sama, Anda harus menginstal babel-plugin-transform-class-properties

npm install -D babel-plugin-transform-class-properties

lalu tambahkan "transform-class-properties" ke .babelrc

{
  "presets": ["env", "react"],
  "plugins": ["react-hot-loader/babel", "transform-class-properties"]
}

statis dapatkan defaultProps() {
kembali {
mobil: "Mercedes"
}

@ Arm7107 Ini tidak efisien karena membuat objek baru setiap kali elemen dibuat. Saya sangat menyarankan untuk tidak menggunakan ini. Tetapkan properti:

MyComponent.defaultProps = {
  // ...
}

atau gunakan sintaks properti kelas statis eksperimental :

class MyComponent extends React.Component {
  static defaultProps = {
    // ...
  };

  // ...
}

(untuk itu Anda memerlukan plugin Babel)

Saya akan mengunci masalah ini untuk mencegah saran salah lebih lanjut yang akan muncul di hasil Google.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat