React: componentDidReceiveProps Tolong

Dibuat pada 27 Feb 2015  ·  94Komentar  ·  Sumber: facebook/react

Saya ingin dengan rendah hati meminta pengait componentDidReceiveProps, sering kali saya ingin melakukan sesuatu pada componentWillMount dan componentWillReceiveProps, tetapi karena this.props belum disetel, saya terpaksa memberikan alat peraga alih-alih membaca langsung dari this.props .

Sebelum Kait Baru

componentWillMount() {
  this.setup(this.props.id);
}

componentWillReceiveProps(next) {
  this.setup(next.id);
}

setup(id) {
  UserActions.load(id);
}

Setelah Kait Baru

componentWillMount() {
  this.setup();
}

componentDidReceiveProps() {
  this.setup();
}

setup() {
  UserActions.load(this.props.id);
}

Dalam contoh sederhana ini mungkin tampak seperti hal kecil, tapi sering kali melewati props berjalan dalam dan bukannya nyaman referensi this.props seseorang dipaksa untuk plumb props seluruh komponen.

Harap pertimbangkan untuk menambahkan componentDidReceiveProps sebagai pengait untuk memanfaatkan kode yang sama yang digunakan dalam componentWillMount tanpa memaksa keduanya untuk memasang props di seluruh komponen.

Komentar yang paling membantu

@syranide Masalahnya adalah ketika pengaturan perlu memanggil metode yang juga membutuhkan alat peraga, yang perlu memanggil metode yang juga membutuhkan alat peraga... Akhirnya seluruh komponen Anda terhubung ke alat peraga.

Semua 94 komentar

Mengapa tidak setup(props) ?

Melihat melalui proyek saya sendiri, saya dapat melihat bahwa saya telah melakukan ini di mana saya memiliki kebutuhan yang sama (yang lain menurunkan sebagian status berdasarkan alat peraga), hanya meneruskan set alat peraga yang berbeda bila diperlukan sehingga Anda hanya perlu melewati sesuatu yang ekstra saat menggunakan kembali, tanpa menduplikasi pengetahuan tentang alat peraga yang dibutuhkan:

setup(props) {
  props = props || this.props
  UserActions.load(props.id)
}

@syranide Masalahnya adalah ketika pengaturan perlu memanggil metode yang juga membutuhkan alat peraga, yang perlu memanggil metode yang juga membutuhkan alat peraga... Akhirnya seluruh komponen Anda terhubung ke alat peraga.

+1 sepertinya sekelompok kabel yang tidak perlu di aplikasi dengan pola saat ini. Bisa menjadi cara standar yang ringkas untuk memecahkan masalah. Terlihat sekelompok orang terbakar di this.props di dalam ComponentWillReceiveProps, tanda yang jelas bahwa itu tidak intuitif.

+1, saya juga merasa ini membuat frustrasi.

Tidak lagi menganggap ini sebagai masalah.

+1, saya juga sering membagikan alat peraga. Mirip dengan @insin di atas saya menggunakan params default untuk sementara waktu:

setup(props = this.props) {
  doSomething(props);
}

Tetapi memutuskan itu adalah anti-pola karena bug halus yang dapat ditimbulkannya jika Anda lupa melewati newProps.

+1

Saya pikir alasan itu tidak tersedia adalah karena this.props dan this.state _always_ sesuai dengan nilai yang diberikan. Tidak ada cara untuk mengimplementasikan componentDidReceiveProps yang tidak memicu render lain tanpa melanggar batasan ini.

Sering kali, jika Anda menggunakan componentWillReceiveProps , Anda sebenarnya menginginkan komponen tingkat tinggi ala Relay , atau sesuatu seperti observe hook yang diusulkan untuk React 0.14 .

+1
Anda juga dapat mengimplementasikan componentDidReceiveProps tanpa mengubah this.props atau this.state . Jika semua yang perlu Anda lakukan adalah membaca dari ini, maka Anda tidak akan memicu render lain. Jika Anda menulis ke props atau state dalam panggilan fungsi yang diusulkan ini, maka Anda menembak diri sendiri, tetapi itu adalah kasus yang sama untuk setiap metode lain dalam siklus hidup.

+1

Saya ingin dapat menanggapi acara alat peraga baru ketika shouldComponentUpdate mengembalikan false , jadi dalam kasus saya, saya tidak dapat menggunakan componentDidUpdate .

+1

+1

Bagaimana dengan componentWillMount dan componentWillUpdate @iammerrick

Saya ingin dapat menanggapi acara alat peraga baru ketika shouldComponentUpdate mengembalikan false, jadi dalam kasus saya, saya tidak dapat menggunakan componentDidUpdate.

Gunakan componentWillReceiveProps ?

+1

+1 ini membantu dengan kode KERING dan menyederhanakan logika.

Saya akan terbuka untuk componentDidReceiveProps dipanggil pada pengaturan awal untuk membuat contoh memulai utas ini hanya satu fungsi:

componentDidReceiveProps() {
  UserActions.load(this.props.id);
}

Pikiran?

componentWillReceiveProps() {
  setTimeout(()=> {
    if(this.isMounted()) {
      this.componentDidReceiveProps();
    }
  });
}
componentDidReceiveProps() {
  UserActions.load(this.props.id);
}

Bagaimana menurutmu?

@YourDeveloperFriend Saya pikir itu tergantung pada cara kerjanya relatif terhadap kait siklus hidup lainnya dan penundaan rendering karena waktu tunggu cascading pada komponen bersarang.

Kait siklus hidup semacam ini harus dipanggil secara sinkron dalam pass yang dijamin akan dipanggil sebelum render. Saya belum mempelajari basis kode React, tetapi saya berasumsi render tidak dipanggil pada batas waktu.

Kemungkinan besar, solusi terbaik adalah dengan mendaftarkan kait pra-rendering atau menandai komponen yang propertinya telah diubah sehingga logika render memanggil componentDidReceiveProps sebelum memanggil render.

+1 tolong. Sangat jelek.

Tidak, aku baik-baik saja. Ada solusi yang lebih baik.

+1

componentDidReceiveProps() sudah ada: disebut render() . Namun mungkin ada kasus (seperti dalam contoh @iammerrick ) di mana Anda perlu memuat/memicu/dll sesuatu sebelum Anda melakukan render. Ini berarti satu dan satu-satunya hal: Anda melakukan sesuatu yang salah.

Ketika Anda melakukan hal-hal seperti

setup(id) {
    UserActions.load(id);
}

Anda memperkenalkan statefullness baik di dalam komponen atau (jauh lebih buruk) di luar. Mengapa Anda perlu load() data setiap kali komponen menerima props (bahkan tidak dijamin new )? Jika Anda melakukan lazy-loading, cara yang tepat adalah dengan meminta data dalam metode render() :

render() {
    var actions = UserActions.load(id);
    if (actions) // render
    else // show spinner or return null, etc.
}

UserActions.load = function(id) {
    if (data) return data;
    else // request the data, emit change on success
}

@robyoder , meneruskan argumen ke fungsi tidak jelek. Ini mungkin tampak terlalu bertele-tele tetapi wajar dalam bahasa pemrograman yang Anda pilih. Menghancurkan API dengan menambahkan metode siklus hidup cadangan hanya untuk mengurangi verbositas jelas sangat buruk.

Jadi beri tahu saya, @me-andre, mengapa kita memiliki componentWillUpdate dan componentWillReceiveProps ?

Menurut pendapat saya, itu karena mereka melayani tujuan yang berbeda dan keduanya membantu. Sama seperti keduanya tidak sama, render tidak sama dengan hipotetis componentDidReceiveProps karena dipanggil untuk alasan selain props baru; plus, Anda tidak diberi akses ke properti sebelumnya.

Manfaat dari props sebelumnya adalah Anda tidak perlu memuat data setiap saat; itu bisa bersyarat berdasarkan alat peraga dan apakah mereka telah berubah.

Jelas, "[kejelekan] ada di mata yang melihatnya", karena menambahkan metode siklus hidup yang tepat sepertinya merupakan solusi yang jauh lebih bersih bagi saya.

Mungkin ada cara lain untuk melihat ini ...

Katakanlah tujuan utama di sini adalah:

(1) kurangi kesalahan manusia - Saya lupa memberikan parameter atau menggunakan props = props || this.props lagi
(2) untuk mengurangi kode boilerplate yang tidak menambah nilai - mengapa menulis sesuatu yang tidak perlu?
(3) untuk mengurangi beban kognitif dalam mencoba memutuskan metode siklus hidup mana yang akan digunakan - mengapa saya perlu memikirkan hal semacam ini, mengapa saya terus menggunakan pendekatan yang sedikit berbeda tergantung pada bagaimana perasaan saya hari itu, dll.

Jadi mungkin ruang solusi adalah seputar penyederhanaan penggunaan React dan React API itu sendiri untuk mencapai tujuan ini.

Jika Anda memikirkan masalah dengan tujuan ini, mungkin beberapa metode siklus hidup dapat digabungkan dan jika Anda tertarik untuk mengetahui inisialisasi vs pembaruan, Anda dapat mengetahuinya dengan tanda tangan/argumen panggilan. Misalnya: beforeRender(prevProps, prevState) atau update(prevProps, prevState) .

Secara pribadi, rasanya ada terlalu banyak metode siklus hidup dan jika mereka dipanggil lebih konsisten (tanpa atau dengan prevProps / prevState pada pass dan pembaruan awal), itu dapat menyederhanakan kode saya dan meningkatkan produktivitas saya. Plus, nama metode siklus hidup cukup panjang (saya cenderung menyalin / menempelkannya daripada mengetiknya) dan sulit untuk mengingat yang akan / memang ada yang membuat saya berpikir mereka bisa / harus disederhanakan.

@robyoder , jawaban singkat mengapa kami memiliki componentWillUpdate dan componentDidReceiveProps apakah ada perbedaan besar di antara keduanya. Mereka serupa tentu saja, tetapi terutama karena diawali dengan componentWill .

| | status telah berubah | komponen tidak diperbarui |
| --- | --- | --- |
| componentWillUpdate() | ya | tidak |
| componentWillReceiveProps() | tidak | ya |

Seperti yang mungkin Anda perhatikan, ada titik/kondisi siklus hidup di mana satu metode dipanggil dan yang lainnya tidak. Itu sebabnya kami memiliki 2 metode siklus hidup yang berbeda.

Namun componentDidReceiveProps() seperti yang dijelaskan dalam topik ini tidak mewakili status atau kondisi komponen apa pun dan tidak memberikan akses ke apa pun yang tidak dimiliki componentWillReceiveProps() . Itu hanya menambahkan sedikit gula sintaksis yang mungkin atau mungkin tidak tampak berguna atau lebih mudah - ini adalah preferensi pribadi, bukan persyaratan teknis . Dan itulah alasan mengapa itu tidak boleh ditambahkan: itu subjektif. Anda mengatakan argumen yang lewat itu jelek - tetapi Anda juga mengatakan "[kejelekan] ada di mata yang melihatnya". Bagi saya sepertinya Anda sudah menjawab sendiri.

@me-andre Anda mungkin menanggapi saya (@kmalakoff) dan @robyoder secara bersamaan. Atau mungkin tidak, tetapi saya akan mengambil kesempatan ini untuk memajukan diskusi ...

Apa yang saya kemukakan adalah bahwa mungkin berpikir di atas API saat ini dengan tiga tujuan di atas dapat memberikan wawasan atau perspektif baru tentang bagaimana seseorang dapat menyederhanakan API untuk mencapainya. Tentu saja, setelah melalui latihan, kita mungkin berakhir di tempat yang sama.

Yuk ikuti latihannya....

Mari kita asumsikan topik ini diikuti dan diberi +1 karena ada sesuatu yang penting di dalamnya dan katakanlah penambahan componentDidReceiveProps bukanlah ide yang baik karena menambah luas permukaan API.

Mengingat tabel dan 3 tujuan yang saya kemukakan, apakah ada yang punya ide untuk menyederhanakan API dan/atau cara lain untuk memberi orang-orang di utas ini apa yang mereka inginkan dan untuk tidak memperluas API (bahkan mungkin mengurangi/menyederhanakannya )?

@kmalakoff , 3 poin yang Anda bicarakan terhubung dengan API hanya karena Anda menggunakan API ketika Anda menemukannya. Mereka tidak disebabkan oleh desain yang buruk.

Masalah pertama yang Anda bicarakan adalah bahwa metode siklus hidup mengambil argumen yang berbeda. Yah, itu sangat alami - mereka melayani tujuan yang berbeda. componentWillReceiveProps mengambil props bukan karena bulan purnama ketika metode ini ditambahkan - tetapi karena ini tentang menerima props yang belum ditetapkan ke komponen. props hanya diteruskan dalam metode yang (mungkin) berbeda dari this.props . Ini sebenarnya petunjuk, bukan masalah.
Masalah # 3 adalah sulit bagi Anda untuk memutuskan panggilan balik/pendekatan mana yang akan digunakan. Yah, itu tidak masalah sampai metode yang saya bicarakan di atas memiliki tanda tangan yang sama. Setelah Anda memiliki state dan this.state , props dan this.props yang sama (baca tidak berarti) di sebagian besar metode, maka Anda terjerat dalam opsi cadangan dan alternatif.
Masalah # 2 adalah tentang kode boilerplate ... yah, React adalah perpustakaan yang tipis - dan itu indah, mudah, dan ketat karena itu. Jika Anda ingin membuat pembungkus yang akan menyederhanakan hidup kita dan mengurangi jumlah kode yang kita tulis setiap hari - mengapa tidak melakukannya? Publikasikan sebagai npm yang bergantung pada react dan selesai.

Mengenai "ada terlalu banyak metode siklus hidup" - belum dan tidak akan pernah terjadi jika Anda berhenti meminta panggilan balik baru yang tidak Anda perlukan secara teknis. Kebutuhan teknis adalah ketika Anda menerapkan komponen yang kompleks dan di tengah pekerjaan Anda mengerti bahwa sama sekali tidak ada cara untuk melakukannya tanpa beberapa peretasan yang buruk. Ini tentang "untuk memicu metode DOM yang rumit, saya perlu sesuatu untuk dipanggil pada saat komponen melakukan X tetapi tidak ada metode seperti itu dan saya tidak dapat menambahkannya, jadi saya menggunakan setTimeout dan mudah-mudahan itu tidak akan mendarat lebih awal dari yang saya butuhkan". Tidak ketika Anda mengatakan "oh, saya bosan menulis alat peraga = this.props".

Dan satu hal lagi...
Dalam aplikasi React yang dirancang dengan baik, Anda tidak memerlukan sebagian besar metode yang kita bicarakan atau Anda jarang menggunakannya. getInitialState , componentWillMount , componentWillUnmount cukup 99% dari waktu. Dalam proyek saya saat ini yang merupakan aplikasi komersial yang relatif besar, componentWillReceiveProps digunakan dua kali di seluruh aplikasi. Saya tidak akan menggunakannya sama sekali, tetapi lingkungan (baca browser) tidak sempurna - memanipulasi hal-hal "stateful-in-itself" tertentu seperti scrollTop atau mengandalkan perhitungan tata letak untuk masa depan render s memerlukan sinkronisasi manual antara transisi props dan perubahan DOM. Namun dalam kebanyakan kasus "normal", Anda tidak perlu tahu kapan transisi props terjadi.

@me-andre berdasarkan pengalaman saya bekerja dengan React, saya yakin ada ruang untuk meningkatkan/menyederhanakan API. Saya tidak sendirian, itulah sebabnya masalah ini diangkat sejak awal dan sedang diberi +1.

Jika saya menjawab dengan memberikan umpan balik pada analisis Anda, saya tidak berpikir itu akan benar-benar memajukan ini (itulah sebabnya saya menghindari melakukannya sejauh ini) karena agak bias terhadap status quo dan membenarkan API saat ini, tetapi Saya akan dengan senang hati memberikan umpan balik tentang solusi potensial! Orang-orang yang terlibat dalam masalah ini mencari untuk mengeksplorasi ide-ide peningkatan dan perubahan API potensial untuk mengatasi masalah yang diangkat melalui pengalaman mereka menggunakan React (seperti yang saya uraikan di atas).

Mungkin Anda benar bahwa komunitas harus melakukan inovasi untuk memajukan API dan mungkin memutarnya kembali ke inti atau mungkin API saat ini sudah sempurna, tetapi saya pikir ini adalah peluang bagus untuk mempertimbangkan seperti apa perubahan itu tim Reaksi.

Mungkin alasan Anda membuat argumen apa adanya adalah karena kami hanya pengguna perpustakaan dengan pemahaman yang kurang mendalam tentang API saat ini dan keputusan yang masuk ke dalamnya. Mungkin Anda bisa menarik beberapa anggota tim React lain yang sama-sama berpengalaman dan berpengetahuan seperti Anda untuk melihat apakah kita mendapatkan perspektif yang berbeda dan bahkan mungkin datang dengan solusi yang bagus atau untuk mendapatkan konsensus bahwa ini sebaik yang didapat?

@kmalakoff , bayangkan React adalah mesin dan 4 roda. Sekarang setiap kali Anda ingin pergi ke suatu tempat, Anda membangun sisa mobil dan itu akhirnya mulai mengganggu. Jika tidak, Anda mengeluh tentang perlunya mengingat detail mesin tingkat rendah dan memutar roda depan dengan tangan tidak terasa benar.
Apa yang saya sarankan adalah untuk mendapatkan kendaraan yang lengkap (kerangka kerja penuh) atau untuk membangun komponen yang diperlukan dengan cara yang dapat Anda gunakan kembali dari waktu ke waktu.
Apa yang saya lihat di thread ini adalah pengguna mesin mengeluh bahwa mesin tidak memiliki sistem hidrolik dan tidak ada lampu interior. Apa yang saya rasakan adalah bahwa kita akan mendapatkan omong kosong lengkap jika kita menambahkan fitur-fitur ini ke tempat yang tidak seharusnya.
React bukanlah framework: ini lebih merupakan mesin rendering bertenaga diff yang mengekspos sistem komponen yang kuat. Ini memiliki API tingkat rendah dan minimalis namun cukup kuat untuk memungkinkan Anda membangun apa pun secara harfiah di atasnya.
Jangan ragu untuk menghubungi saya melalui email jika Anda merasa perlu mengklarifikasi sesuatu - saya tidak ingin utas ini menjadi tutorial.

@me-andre Saya yakin kami memahami posisi Anda dan argumen Anda dengan baik sekarang. Terima kasih! Anda mungkin benar bahwa API sudah sebagus yang akan didapat, tetapi ada juga kemungkinan bahwa itu dapat ditingkatkan.

Bisakah seseorang mengajukan alasan untuk mengubah API? misalnya. menyediakan analisis komparatif dari berbagai opsi (tambahkan componentDidReceiveProps vs gabungkan / sederhanakan API vs tidak ada perubahan)

Tim React telah mengamati masalah ini, dan kami mendiskusikannya secara internal. Pada prinsipnya, saya selalu condong ke arah menghilangkan area permukaan API, jadi saya menemukan diri saya condong ke argumen @me-andre. Namun, tim kami terkadang dengan sayang menyebut componentDidReceiveProps sebagai "metode siklus hidup yang hilang", dan ada diskusi serius tentang kemungkinan menambahkannya. Yang penting adalah kita mengaktifkan praktik terbaik tanpa memicu praktik buruk.

Apa yang paling berguna bagi kami (atau setidaknya saya) adalah memiliki pemahaman yang kuat tentang MENGAPA orang menginginkan metode siklus hidup ini. Apa yang Anda coba lakukan dalam siklus hidup ini yang tidak cukup tercakup oleh metode siklus hidup lainnya? Mengapa seseorang ingin melakukan UserActions.load(id); dalam componentDidReceiveProps alih-alih dalam render seperti yang disarankan di https://github.com/facebook/react/issues/3279#issuecomment -163875454 (Saya dapat memikirkan alasan, tapi saya ingin tahu apa alasan Anda)? Apakah ada kasus penggunaan selain memulai pemuatan data berdasarkan alat peraga?

@jimfb Saya percaya bahwa componentDidReceiveProps adalah persis apa yang saya butuhkan dan metode lain tidak pantas, tapi saya bisa saja salah. Saya akan dengan senang hati menjelaskan kasus penggunaan saya.

Saya memiliki rute di react-router yang terlihat seperti ini:

    <Route path="/profile/:username" component={ProfilePage} />

Saya perlu mengambil data untuk profil dari sumber eksternal, dan untuk melakukannya dengan benar, saya perlu membuat permintaan HTTP dalam metode componentDidMount .

Sayangnya, ketika saya menavigasi dari satu profil ke profil lainnya, React Router tidak memanggil metode konstruktor atau metode componentDidMount lagi (tentu saja ini bisa menjadi bug tetapi saya akan menganggap itu bukan untuk saat ini) .

Saya berpikir untuk memperbaikinya dengan menggunakan teori componentDidReceiveProps . Sayangnya itu belum ada, dan componentWillReceiveProps tidak akan melayani kebutuhan saya.

Setiap petunjuk tentang ini akan sangat dihargai.

Firasat saya adalah bahwa componentDidReceiveProps adalah persis apa yang saya butuhkan.

@ shea256 Bisakah Anda menjelaskan mengapa componentWillReceiveProps tidak memenuhi kebutuhan Anda?

@ shea256 Juga, mengapa komponen Anda perlu membuat permintaan HTTP? Apa isi permintaan http itu? Jika data, mengapa Anda tidak memperbarui komponen Anda secara asinkron saat panggilan balik data kembali?

@jimfb Kasus umum bagi saya adalah ketika kita harus memuat sesuatu secara tidak sinkron sebagai respons terhadap perubahan prop, yang melibatkan pengaturan beberapa status untuk menunjukkan bahwa pemuatan sedang terjadi dan kemudian ketika data dimuat, mengatur status itu.

Memasang dan menerima props baru harus memicu siklus pemuatan yang sama, jadi componentDidMount dan componentWillReceiveProps adalah tempat untuk memanggil fungsi update. render tidak memiliki info apakah itu prop baru, lagi pula, setState dari render tidak boleh.

Jadi, saya punya satu fungsi yang melakukan pemuatan. Tetapi saya harus memasukkan props sebagai parameter dan dengan hati-hati menghindari penggunaan this.props yang kedaluwarsa untuk componentWillReceiveProps . Ini pasti berakhir menyebabkan bug karena Anda harus ingat untuk menggunakan alat peraga yang diteruskan atau Anda mendapatkan kesalahan halus di belakang ketika perubahan tiba. Dan tanda tangan dari semua metode yang terlibat lebih kompleks karena alat peraga harus diteruskan.

Ya, itu bisa dilakukan dengan api saat ini. Tetapi itu menyebabkan kode yang lebih kikuk dan rawan kesalahan yang secara umum sangat baik dihindari oleh React.

@jimfb saya perlu mendapatkan nama pengguna baru di routeParam dan dengan componentWillReceiveProps saya belum memilikinya.

Saya perlu membuat permintaan HTTP untuk memuat data profil dari sumber eksternal (data tidak disimpan secara lokal).

Dan saya dapat memperbarui komponen saya dalam metode render tetapi rasanya agak kotor:

constructor(props) {
  super(props)

  this.state = {
    id: this.props.routeParams.id,
    profile: {}
  }
}

componentDidMount() {
  this.getProfile(this.state.id)
}

render() {
  if (this.props.routeParams.id !== this.state.id) {
    this.getProfile(this.props.routeParams.id)
  }

  return (
    <div>
      <div className="name">
       {this.state.profile.name}
      </div>
    </div>
  )
}

@grassick menulis:

Kasus umum bagi saya adalah ketika kita harus memuat sesuatu secara tidak sinkron sebagai respons terhadap perubahan prop, yang melibatkan pengaturan beberapa status untuk menunjukkan bahwa pemuatan sedang terjadi dan kemudian ketika data dimuat, mengatur status itu.

Ya, ini persis kasus penggunaan saya.

Memasang dan menerima props baru harus memicu siklus pemuatan yang sama ini, jadi componentDidMount dan componentWillReceiveProps adalah tempat untuk memanggil fungsi update.

kata baik.

@ shea256 tidak bisakah ini dilakukan menggunakan componentWillReceiveProps saja?

constructor(props) {
  super(props)

  this.state = {
    id: this.props.routeParams.id,
    profile: {}
  }
}

componentDidMount() {
  this.getProfile(this.state.id)
}

componentWillReceiveProps(nextProps) {
  let { id } = nextProps.params
  if(id !== this.state.id) {
    this.getProfile(id, (profile) => {
      this.setState({ id: id, profile: profile })
    })
  }
}

render() {
  return (
    <div>
      <div className="name">
       {this.state.profile.name}
      </div>
    </div>
  )
}

@grassick menulis:

Kasus umum bagi saya adalah ketika kita harus memuat sesuatu secara tidak sinkron sebagai respons terhadap perubahan prop, yang melibatkan pengaturan beberapa status untuk menunjukkan bahwa pemuatan sedang terjadi dan kemudian ketika data dimuat, mengatur status itu.

@grassick menulis:

render tidak memiliki info apakah itu prop baru, dan lagi pula, setState dari render adalah tidak-tidak.

Hanya meludah di sini: Jika componentDidUpdate dipanggil pada render awal (selain render berikutnya), apakah itu akan menyelesaikan kasus penggunaan Anda? Anda dapat memeriksa apakah alat peraga berubah dan melakukan semua pemuatan data Anda di componentDidUpdate , bukan? Dan dalam render, Anda akan tahu bahwa Anda sedang memuat data jika this.state.profileName != this.props.profileName . Apakah alternatif itu cukup untuk kasus penggunaan Anda?


Apakah ada kasus penggunaan yang dimiliki orang yang TIDAK melibatkan komponen yang memuat data berdasarkan alat peraga?

@calmdev hm, saya yakin Anda benar. Saya akan mencobanya.

@jimfb mungkin, meskipun saya mencoba menggunakan componentDidUpdate dan saya pikir itu tidak berhasil. Aku bisa melihat lagi.

Dan sepertinya saya benar-benar dapat melakukan pemeriksaan pada this.state.profileName != this.props.profileName tetapi ini juga tampak seperti peretasan, bukan? Pada titik ini, jika componentWillReceiveProps(nextProps) akhirnya berfungsi, saya lebih suka itu. Sekarang, yang mengganggu saya adalah kurangnya simetri dengan componentDidMount . Bisakah saya menggunakan componentWillMount sebagai pengganti componentDidMount ?

Saya hanya merasa seluruh siklus hidup bisa lebih bersih.

@ shea256 , saya punya pertanyaan untuk Anda... README untuk Bereaksi?
Saya tidak merasa nyaman mengatakan itu tetapi jika tidak, Anda mungkin tidak boleh meminta fitur baru untuk alat yang tidak Anda kenal. Bagi saya itu bahkan terdengar... tidak masuk akal.
"Bisakah saya menggunakan componentWillMount sebagai pengganti componentDidMount ?"
Tidak, Anda tidak bisa karena seperti yang dinyatakan dalam readme, componentWillMount dipanggil sebelum komponen Anda masuk ke DOM dan componentDidMount - setelah itu. Nah, Anda pasti dapat mengganti satu metode dengan yang lain dan itu hanya akan merusak kode Anda. Alasan kami memiliki 2 metode di sini bukanlah estetika (baca "simetri"). Itu karena kita mungkin memerlukan satu metode untuk melakukan persiapan sebelum kita membuat dan yang lainnya untuk beberapa kueri/manipulasi DOM awal setelah render pertama. Tetapi bahkan itu eksotis untuk komponen React rata-rata. Biasanya, Anda tidak perlu mengakses DOM secara manual.
"Dan sepertinya aku benar-benar bisa memeriksa this.state.profileName != this.props.profileName tapi ini juga terlihat seperti peretasan, bukan?"
Ya, seluruh pendekatan Anda adalah peretasan. Dan siapa yang bilang componentDidReceiveProps akan menjamin props telah diubah? Tidak ada yang akan melakukan itu kecuali Anda mendefinisikan shouldComponentUpdate .
Ini hanya cara React bekerja.

@me-andre terima kasih telah melompat, tetapi Anda terlalu kasar untuk selera saya. Juga saya tidak percaya Anda mengerti pertanyaan saya. Saya cukup familiar dengan apa yang dilakukan componentWillMount dan componentDidMount . Saya akan menunggu tanggapan @jimfb .

@shea256 ,
"Aku juga tidak percaya kamu mengerti pertanyaanku."
Bisakah Anda menunjukkan di mana saya melewatkan poin ketika saya menjawab pertanyaan Anda?
Juga, bisakah Anda menjelaskan apa yang Anda coba tanyakan.
Juga, kami di sini bukan untuk membahas kepribadian atau selera. Ini bukan pembicaraan pribadi, juga bukan dukungan teknis. Ini bahkan bukan situs pertukaran tumpukan di mana Anda dapat mengharapkan seseorang untuk memandu Anda melalui beberapa bidang pengetahuan.
Saya sering berbicara di pertemuan lokal serta konferensi internasional tentang React (dan tidak hanya) dan saya sangat terbuka untuk berbagi pengetahuan - kapan dan di mana itu tepat. Anda selalu dapat menghubungi saya secara langsung melalui email atau skype.

Mengenai masalah Anda dengan memuat data profil. Anda mencoba memecahkan masalah penerapan pendekatan imperatif klasik ke kerangka kerja berorientasi fungsional. Tampilan di React adalah fungsi dari props, state, dan environment. Seperti function(state, props) { return // whatever you've computed from it } (tetapi hal-hal menjadi sedikit lebih kompleks di dunia nyata - jika tidak, React tidak akan ada sama sekali). Meskipun di 0.14 kita mendapatkan komponen fungsional murni, untuk sebagian besar komponen fungsi entri ini

Ini berarti Anda mulai menulis dari render() dan Anda menganggap props Anda selalu up to date dan Anda tidak peduli apakah props telah diubah atau tidak, berapa kali dan di mana . Kasing Anda dapat diimplementasikan dengan cara berikut:

// profile-view.js

var React = require('react');

module.exports = React.createClass({
    contextTypes: {
        app: React.PropTypes.object.isRequired
        // another option is var app = require('app')
        // or even var profiles = require('stores/profiles')
    },
    componentWillMount() {
        var {app} = this.context; // another option is to require('app')
        app.profiles.addListener('change', this.onStoreChange);
    },
    componentWillUnmount() {
        var {app} = this.context; // another option is to require('app')
        app.profiles.removeChangeListener('change', this.onStoreChange);
    },
    onStoreChange() {
        this.forceUpdate();
    },
    render() {
        var {app} = this.context;
        var profile = app.profiles.read(this.props.routeParams.id);
        if (profile) { // profile's been loaded
            return <div>{profile.name}</div>;
        } else { // not yet
            return <div>Loading...</div>;
        }
    }
});

// profiles-store.js
// app.profiles = new Profiles() on app initialization

var EventEmitter = require('events');
var {inherits} = require('util');

module.exports = Profiles;

function Profiles() {
    this.profiles = {};
}

inherits(Profiles, EventEmitter);

Profiles.prototype.read = function(id) {
    var profile = this.profiles[id];
    if (!profile) {
        $.get(`profiles/${id}`).then(profile => {
            this.profiles[id] = profile;
            this.emit('change');
        });
    }
    return profile;
};

Cukup mudah.
Dan Anda tidak perlu componentDidReceiveProps . Anda bahkan tidak perlu componentWillReceiveProps dan kait serupa. Jika Anda pernah merasa membutuhkannya untuk kasus sepele, Anda kehilangan pemahaman tentang bagaimana melakukan sesuatu di React. Dalam rangka untuk mendapatkannya silahkan gunakan sumber daya yang tepat, tidak hanya sampah Isu bagian dari repositori. Rasanya agak terlalu kasar untuk selera saya. Bahkan terasa seperti Anda tidak menghargai waktu orang lain.

@me-andre Mungkin ada baiknya sedikit mengurangi bahasa Anda, karena dapat terlihat sedikit konfrontatif meskipun Anda hanya mencoba membantu. Kami ingin menciptakan komunitas yang ramah untuk semua orang; kami semua pemula pada satu titik. Meskipun Anda benar tentang beberapa poin Anda pada API/desain, fakta bahwa begitu banyak orang memberi +1 pada masalah ini merupakan indikasi bahwa ada sesuatu yang salah, jadi kami harus mencoba memahami apa/mengapa orang menginginkan ini lingkaran kehidupan. Mungkin masalahnya adalah kami tidak cukup mengkomunikasikan cara menulis komponen (dokumentasi) dengan benar, atau mungkin API React perlu diubah - bagaimanapun juga, ada baiknya memahami keluhan/pertanyaan/komentar di sini.

@ shea256 this.state.profileName != this.props.profileName sedang memeriksa untuk melihat apakah keadaan internal (apa yang dirender oleh komponen) cocok dengan apa yang diminta induk untuk dirender oleh komponen. Ini hampir seperti definisi "komponen sedang diperbarui" atau "komponen mutakhir", jadi saya tidak melihatnya sebagai peretasan. Setidaknya, tidak lebih hacky daripada gagasan "menyalakan permintaan pembaruan data ketika prop berubah dan melakukan setstate di panggilan balik" adalah di tempat pertama.

@ shea256 Untuk lebih jelasnya: siklus hidup yang diusulkan ini tidak akan memungkinkan Anda melakukan apa pun yang belum dapat Anda lakukan hari ini dengan siklus hidup saat ini. Itu hanya akan membuatnya berpotensi lebih nyaman. Seperti yang telah disebutkan orang lain, apa yang Anda coba lakukan dimungkinkan dengan siklus hidup saat ini (ada beberapa kombinasi siklus hidup yang memungkinkan Anda mencapai tujuan Anda). Jika Anda mencoba "membuatnya berfungsi", maka StackOverflow akan menjadi tempat yang lebih baik untuk berdiskusi. Masalah github ini mencoba memahami perlunya componentDidReceiveProps karena berkaitan dengan ergonomi pengembang.

Dan siapa yang memberitahu Anda componentDidReceiveProps akan menjamin props telah diubah?

@me-andre benar di sini. Sebagian besar metode siklus hidup tidak benar-benar menjamin bahwa sesuatu telah berubah; mereka hanya menunjukkan bahwa sesuatu _mungkin_ telah berubah. Untuk alasan ini, Anda selalu perlu memeriksa apakah previous === next jika Anda akan melakukan sesuatu seperti membuat permintaan http. Sekelompok orang di utas ini tampaknya membuat asumsi bahwa nilainya telah berubah hanya karena metode siklus hidup diaktifkan.

@me-andre menulis:

Anda mencoba memecahkan masalah penerapan pendekatan imperatif klasik ke kerangka kerja berorientasi fungsional.

Saya pikir ini mungkin penyebab utama orang menginginkan metode siklus hidup baru ini, tetapi saya masih mencoba mencari tahu mengapa/bagaimana orang ingin menggunakan metode ini. Sangat mungkin bahwa semantik siklus hidup saat ini sedikit tidak selaras dengan apa yang biasanya ingin dilakukan orang.

Semua: Apakah ada kasus penggunaan untuk componentDidReceiveProps selain "memuat data secara tidak sinkron sebagai respons terhadap perubahan prop"?

cc @grassick @iammerrick

@jimfb Saya mencari kode saya dan saya juga menggunakan componentWillReceiveProps untuk membuat objek mahal yang diperlukan untuk render. Kasus ini mengalami masalah yang sama yang harus melewati props dan berhati-hatilah untuk tidak menggunakan this.props dalam kode.

@jimfb menulis:

@me-andre Mungkin ada baiknya sedikit mengurangi bahasa Anda, karena dapat terlihat sedikit konfrontatif meskipun Anda hanya mencoba membantu. Kami ingin menciptakan komunitas yang ramah untuk semua orang; kami semua pemula pada satu titik. Meskipun Anda benar tentang beberapa poin Anda pada API/desain, fakta bahwa begitu banyak orang memberi +1 pada masalah ini merupakan indikasi bahwa ada sesuatu yang salah, jadi kami harus mencoba memahami apa/mengapa orang menginginkan ini lingkaran kehidupan. Mungkin masalahnya adalah kami tidak cukup mengkomunikasikan cara menulis komponen (dokumentasi) dengan benar, atau mungkin API React perlu diubah - bagaimanapun juga, ada baiknya memahami keluhan/pertanyaan/komentar di sini.

Terima kasih telah menyebutkan ini. Sangat penting untuk memastikan Anda memiliki komunitas yang ramah dan komunikasi saya dengan Anda hanya menyenangkan.

@jimfb menulis:

@shea256 this.state.profileName != this.props.profileName sedang memeriksa untuk melihat apakah status internal (apa yang dirender oleh komponen) cocok dengan apa yang diminta induk untuk dirender oleh komponen. Ini hampir seperti definisi "komponen sedang diperbarui" atau "komponen mutakhir", jadi saya tidak melihatnya sebagai peretasan. Setidaknya, tidak lebih hacky daripada gagasan "menyalakan permintaan pembaruan data ketika prop berubah dan melakukan setstate di panggilan balik" adalah di tempat pertama.

Ya, ini tampaknya masuk akal.

@jimfb menulis:

@ shea256 Untuk lebih jelasnya: siklus hidup yang diusulkan ini tidak akan memungkinkan Anda melakukan apa pun yang belum dapat Anda lakukan hari ini dengan siklus hidup saat ini. Itu hanya akan membuatnya berpotensi lebih nyaman. Seperti yang telah disebutkan orang lain, apa yang Anda coba lakukan dimungkinkan dengan siklus hidup saat ini (ada beberapa kombinasi siklus hidup yang memungkinkan Anda mencapai tujuan Anda). Jika Anda mencoba "membuatnya berfungsi", maka StackOverflow akan menjadi tempat yang lebih baik untuk berdiskusi. Masalah github ini mencoba memahami perlunya componentDidReceiveProps karena berkaitan dengan ergonomi pengembang.

Saya sangat setuju dengan ini. Saya tidak memposting kasus penggunaan khusus saya untuk menerima bantuan tentangnya. Saya memposting untuk memberikan beberapa wawasan tentang mengapa saya pikir componentDidReceiveProps akan berguna.

Saya dan lebih dari selusin orang lain yang memposting jelas memiliki naluri untuk menggunakan sesuatu seperti ini (yang berarti kemungkinan ada ratusan atau ribuan lainnya), yang menunjukkan kepada saya bahwa API tidak seintuitif mungkin.

@jimfb menulis:

@me-andre benar di sini. Sebagian besar metode siklus hidup tidak benar-benar menjamin bahwa sesuatu telah berubah; mereka hanya menunjukkan bahwa sesuatu mungkin telah berubah. Untuk alasan ini, Anda selalu perlu memeriksa apakah sebelumnya === berikutnya jika Anda akan melakukan sesuatu seperti membuat permintaan http. Sekelompok orang di utas ini tampaknya membuat asumsi bahwa nilainya telah berubah hanya karena metode siklus hidup diaktifkan.

Saya tidak membuat asumsi ini. Saya memang meninggalkan cek tetapi sekarang saya menggunakannya. Tetapi dalam kasus terburuk, permintaan tambahan akan dipicu.

@jimfb menulis:

Saya pikir ini mungkin penyebab utama orang menginginkan metode siklus hidup baru ini, tetapi saya masih mencoba mencari tahu mengapa/bagaimana orang ingin menggunakan metode ini. Sangat mungkin bahwa semantik siklus hidup saat ini sedikit tidak selaras dengan apa yang biasanya ingin dilakukan orang.

Mungkin. Saya akan lebih memikirkan ini.

componentDidReceiveProps akan sangat membantu untuk kasus penggunaan khusus yang saya miliki.

Saya menggunakan arsitektur ReactRouter dan Flux. Ketika komponen saya dipakai, saya mengatur status saya ke item dari toko. Ketika toko itu mengeluarkan acara perubahan, saya memperbarui status saya menggunakan kueri pengambilan yang sama.

Ketika alat peraga saya berubah karena saya menavigasi ke ID item yang berbeda di rute yang sama, saya perlu menanyakan toko saya lagi atau komponen saya akan terjebak dengan status dari item sebelumnya di toko.

Saat ini, ketika componentWillReceiveProps dipanggil, saya memeriksa untuk melihat apakah ada parameter rute saya yang berubah, dan jika berubah, saya memanggil updateItemState. Tapi, karena alat peraganya belum benar-benar berubah, saya sekarang harus memasukkan alat peraga ke dalam metode saya.

this.updateItemState( nextProps );

updateItemState( props ) {
    props = props || this.props;

    this.setState( {
        item: this.getItemState( props )
    } );
}

getItemState( props ) {
    props = props || this.props;

    return this.ItemStore.get( props.params[ this.paramName ] );
}

hanya akan menjadi

this.updateItemState();

updateItemState() {
    this.setState( {
        item: this.getItemState()
    } );
}

getItemState() {
    return this.ItemStore.get( this.props.params[ this.paramName ] );
}

Saya merasa bahwa ini adalah kasus penggunaan yang masuk akal.

@akinnee-gl dkk: Jika componentDidUpdate dipecat setelah pemasangan awal selain pembaruan, apakah itu akan menyelesaikan kasus penggunaan Anda?

@akinnee-gl , jika Anda menggunakan Flux, maka Anda tidak perlu mengatur status dari toko. Kecuali itu benar-benar tidak mungkin, Anda harus mempertahankan keadaan di satu tempat. Ketika datang ke Flux tempat itu adalah toko itu sendiri. Ketika toko mengeluarkan uang receh, Anda hanya forceUpdate() dan kemudian di render() Anda read() toko Anda.

"Ketika alat peraga saya berubah karena saya menavigasi ke ID item yang berbeda di rute yang sama, saya perlu menanyakan toko saya lagi atau komponen saya akan terjebak dengan status dari item sebelumnya di toko."

Tidak pernah.

Lihatlah: Anda perlu merender item tertentu dari toko dan item mana yang akan dirender Anda putuskan dari props . Jika itu adalah kebutuhan Anda, itu harus dinyatakan dalam kode dengan cara yang sama seperti dalam kata-kata:

    var item = this.props.store.read(this.props.id);
    return <div>{item.name}</div>;

Ini adalah komponen Anda, tidak lebih.
Untuk membuat permainan ini dengan Flux, Anda dapat menulis komponen yang dapat digunakan kembali untuk pengikatan/pemutusan toko:

<FluxWrapper store={store} component={Component} id={this.props.routeParams.id} />

var FluxWrapper = React.createClass({
    componentWillMount() {
        this.props.store.addListener('change', this.onStoreChange);
    },
    componentWillUnmount() {
        this.props.store.removeListener('change', this.onStoreChange);
    },
    onStoreChange() {
        this.forceUpdate();
    },
    render() {
        var Component = this.props.component;
        return <Component {...this.props} />;
    }
});

var Component = React.createClass({
    render() {
        var item = this.props.store.read(this.props.id);
        return <div>{item.name}</div>;
    }
});

Lihat betapa kecilnya komponen Anda jika Anda menggunakan React dengan benar.

Namun jika toko Anda berat dan Anda tidak bisa hanya read() mereka pada setiap render() , maka Anda memerlukan middleware caching. Ini dapat berupa komponen yang dapat digunakan kembali (mirip dengan FluxWrapper ) atau toko proxy perantara yang menutupi metode read() . Toko proxy mudah dan keren - mereka tidak hanya dapat membaca cache tetapi juga menekan perubahan jika perubahan toko induk tidak penting atau signifikan untuk kasus ini.
Ini disebut komposisi. Anda harus lebih memilih komposisi daripada pewarisan atau perluasan fungsionalitas atau apa pun karena komposisi berskala .
Segera setelah Anda mendapatkan masalah yang sulit diselesaikan dengan menggunakan satu komponen, harap pertimbangkan untuk menggunakan 2 atau lebih komponen daripada menambahkan kerumitan pada komponen yang ada.

@jimfb , mengenai nada saya: Saya bukan penutur asli bahasa Inggris dan bahkan tidak memiliki latihan berbicara yang teratur, jadi saya terkadang memilih kata yang salah - saya hanya tidak merasakan bagaimana mereka terdengar secara emosional.

Pendekatan yang menarik. Saya akan mengingatnya. Semua dokumen resmi untuk React mengatakan untuk menjaga fungsi render Anda tetap murni (artinya Anda hanya boleh mengakses props dan menyatakan dalam metode render). Semua contoh Flux menunjukkan status pengaturan dari toko.

@jimfb Masalah dengan componentDidUpdate adalah bahwa ia dipanggil untuk alasan lain selain perubahan alat peraga. Juga, saya harus menunggu hingga komponen telah diperbarui, lalu panggil setState untuk memperbaruinya lagi! Tampaknya cukup tidak efisien.

@akinnee-gl componentWillReceiveProps juga dapat dipanggil untuk alasan selain perubahan alat peraga (lihat: https://github.com/facebook/react/issues/3279#issuecomment-164713518), jadi Anda HARUS memeriksa untuk melihat jika prop benar-benar berubah (terlepas dari siklus hidup mana yang Anda pilih). Juga, jika Anda benar-benar melakukan data asinkron, Anda akan menunggu loop acara berikutnya sebelum panggilan balik Anda akan dipecat, jadi saya rasa tidak masalah jika fungsi Anda dipanggil segera sebelum/setelah Anda fungsi render, kan?

@jimfb Sebenarnya, jika item yang dirujuk prop sudah ada di store, tidak perlu di-render lagi. Jika belum ada di toko, kami mungkin ingin menampilkan layar pemuatan. Jadi masih tidak masuk akal untuk membuat dua kali. Saya melihat apa yang Anda katakan meskipun.

@ saya-andre Saya sangat suka pendekatan Anda hanya membaca dari toko selama render. Tampaknya menyederhanakan kode. Saya khawatir Anda kehilangan efisiensi dengan melakukan itu. Anda kehilangan kemampuan untuk mengontrol pembaruan melalui shouldComponentUpdate, dan Anda harus menambahkan komponen FluxWrapper tambahan yang Anda sebutkan. Ada pemikiran tentang itu?

Saya telah memantau diskusi dan saya ingin memunculkan kembali opsi ketiga: (1) API sangat bagus, (2) perlu componentDidReceiveProps, dan (3) mungkin ada API yang lebih sederhana.

Saya melihat masalah sebagai peluang untuk melihat apakah kita dapat memecahkan kebutuhan mendasar yang diangkat oleh masalah ini dengan melakukan brainstorming lebih dalam untuk mengubah API daripada membatasi diskusi ke ruang solusi dari (1) dan (2).

API yang disederhanakan dapat didasarkan pada prinsip-prinsip berikut:

(A) menyederhanakan struktur kode / mengurangi boilerplate
(B) pisahkan props (input) dari state (internal)

Alasan utama untuk (A) adalah karena saya mendapati diri saya menulis boilerplate yang tidak menambah nilai. Contoh:

componentWillMount() { this.actuallyCheckThePropsAndMaybeDoSomething(); }
componentWillReceiveProps(nextProps) { this.actuallyCheckThePropsAndMaybeDoSomething(nextProps); }

actuallyCheckThePropsAndMaybeDoSomething(props) {
  props = props || this.props;

  let relatedProps1 = _.pick(props, KEYS1);
  if (!shallowEqual(this.relatedProps1, relatedProps1) { // changed
   this.relatedProps1 = relatedProps1;

   // do something
  }

  let relatedProps2 = _.pick(props, KEYS2);
  if (!shallowEqual(this.relatedProps1, relatedProps2) { // changed
   this.relatedProps2 = relatedProps2;

   // do something else
  }
}

Saya lebih suka melakukan yang berikut dan tidak memiliki jalur kode terpisah untuk pertama kali vs diubah:

propsUpdated(prevProps) {
  if (!shallowEqual(_.pick(prevProps || {}, KEYS1), _.pick(this.props, KEYS1)) { // changed
   // do something
  }

  if (!shallowEqual(_.pick(prevProps || {}, KEYS2), _.pick(this.props, KEYS2)) { // changed
   // do something
  }
}

Adapun (B), masalah utama dengan componentDidUpdate seperti yang baru saja disebutkan adalah bahwa Anda dapat memicu panggilan metode berulang jika Anda menetapkan status karena perubahan properti karena dipanggil untuk status props (input) dan (internal). Jalur kode ini tampaknya lebih baik karena dipisahkan karena alat peraga dipasok dari luar dan status diatur di dalam, mis. Saya telah mencoba/mempertimbangkan kemungkinan keempat dari updated(prevProps, prevState) (nama yang disederhanakan untuk componentDidUpdate karena lebih sedikit metode siklus hidup yang memungkinkan penamaan yang lebih pendek) menggunakan componentDidUpdate untuk mengurangi boilerplate, tetapi saya merasa sedikit tidak puas dengan potensi detik yang berlebihan memperbarui panggilan dan bahwa logikanya tampaknya cukup independen dalam praktiknya.

Berdasarkan memulai dengan prinsip-prinsip desain (saya yakin ada lebih banyak lagi!), Saya bertanya-tanya apakah sesuatu seperti propsUpdated dan stateUpdated bisa menjadi opsi ketiga yang potensial untuk diskusi ini ?

@kmalakoff Anda akan selalu perlu memeriksa apakah props berubah, karena kami tidak akan pernah dapat memberi tahu Anda secara pasti bahwa props berubah/tidak (karena Javascript tidak memiliki tipe nilai dan memang memiliki mutabilitas).

Pada catatan itu, mungkin itu bisa memanggil shouldComponentUpdate untuk memberi tahu apakah itu harus memanggil propsDidChange atau apa pun. Masalah terpisah sekalipun.

@jimfb tidak mengikuti dengan tepat apa batasan bahasa yang Anda maksud dan bagaimana kaitannya dengan menyederhanakan API secara umum. Bisakah Anda menjelaskan sedikit lebih detail atau dengan contoh? Saya perlu penjelasan ini disederhanakan / diperluas sedikit untuk dipahami ...

Saya pikir maksudnya bahwa tidak ada cara cepat bawaan untuk memeriksa apakah this.props === nextProps karena mereka mungkin atau mungkin bukan dua objek terpisah.

{ a: 1 } === { a: 1 } menghasilkan false karena mereka adalah dua objek yang terpisah, tetapi

var a = { a: 1 };
var b = a;
a === b

menghasilkan true karena keduanya sebenarnya adalah referensi ke objek yang sama.

Kami dapat secara rekursif memeriksa setiap properti untuk kesetaraan, tetapi itu bisa sangat lambat. Itu sebabnya terserah kita untuk mengimplementasikan shouldComponentUpdate

@kmalakoff Saya tidak ingin menyimpang dari utas ini, tetapi inilah intinya untuk Anda: https://Gist.github.com/jimfb/9ef9b46741efbb949744

TLDR: @akinnee-gl benar sekali dalam penjelasannya (Terima kasih!). Dengan koreksi kecil bahwa kami tidak selalu dapat melakukan pemeriksaan rekursif (bahkan jika kami menginginkannya, dan kinerja tidak menjadi masalah), karena tidak ada cara untuk memeriksa secara rekursif fungsi panggilan balik yang diteruskan sebagai prop.

Mari kita tetap utas ini pada topik: P.

Terima kasih semuanya! Hmmm, masih belum sepenuhnya jelas mengapa menyederhanakan API bukanlah pilihan untuk menyelesaikan masalah ini. Saya akan menambahkan komentar ke intinya ...

Jika ada yang ingin berpartisipasi dalam solusi yang lebih luas, silakan bergabung dengan kami di sana!

@jimfb @calmdev Saya sudah mencoba saran Anda dan sekarang saya memahami sepenuhnya mengapa componentDidReceiveProps tidak benar-benar menambahkan sesuatu yang baru dan tidak boleh ditambahkan sebagai fungsi tambahan. Sementara saya mempercayai kata-kata Anda sebelumnya, sekarang masuk akal secara intuitif bagi saya mengapa ini terjadi.

Untuk mengilustrasikan bagaimana saya sampai pada realisasi ini, saya ingin membagikan kode terbaru saya. Mungkin ini akan dapat membantu orang lain juga.

Lihatlah komponen halaman profil saya:

class ProfilePage extends Component {
  static propTypes = {
    fetchCurrentProfile: PropTypes.func.isRequired,
    currentProfile: PropTypes.object.isRequired
  }

  constructor(props) {
    super(props)
    this.state = { currentProfile: {} }
  }

  componentHasNewRouteParams(routeParams) {
    this.props.fetchCurrentProfile(routeParams.id)
  }

  componentWillMount() {
    this.componentHasNewRouteParams(this.props.routeParams)
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.routeParams.id !== this.props.routeParams.id) {
      this.componentHasNewRouteParams(nextProps.routeParams)
    }
    this.setState({
      currentProfile: nextProps.currentProfile
    })
  }

  render() {
    var profile = this.state.currentProfile
    return (
      <div>
        <h1>{ profile.name ? profile.name : null }</h1>
      </div>
    )
  }
}

Saat komponen dipasang, komponen tidak memiliki data profil dan perlu memuat profil dari sumber eksternal.

Jadi... Saya memintanya memanggil fungsi fetchCurrentProfile (dibungkus componentHasNewIdProp ) yang mengambil data dari sumber eksternal, kemudian mengirimkan tindakan pembaruan ke Redux. Peredam menerima tindakan ini dan memperbarui status aplikasi, yang kemudian memperbarui props untuk komponen ProfilePage .

Sekarang, karena props telah diperbarui, fungsi componentWillReceiveProps dipanggil. Tapi kita tidak tahu konteks acara perubahan prop, jadi kita perlu mencari tahu props mana (jika ada) yang telah diubah. Kami melihat bahwa IDnya sama, jadi kami tidak perlu memanggil fetchCurrentProfile lagi. Kemudian kami memperbarui state.currentProfile sehingga komponen mengetahui untuk merender ulang dengan data profil baru (ya saya bisa melakukan ini dengan alat peraga, tetapi ada alasan lain untuk ini yang tidak ingin saya bahas di sini). Saat ini, kami dapat memeriksa untuk melihat apakah props.currentProfile telah berubah sebelum memperbarui status, tetapi ini bukan operasi yang mahal sehingga tidak masalah jika kami memeriksanya.

Lalu... misalkan kita ingin bernavigasi dari satu profil ke profil lainnya. Kami klik link dan router memicu perubahan rute. Kami sekarang memiliki parameter rute baru dan fungsi componentWillReceiveProps terpicu. Kami melihat bahwa id telah berubah dan kami memanggil fetchCurrentProfile lagi (melalui componentHasNewIdProp ).

Saat pengambilan baru kembali dan mengirimkan tindakan redux, prop currentProfile diperbarui lagi, status kemudian diperbarui, dan komponen dirender ulang dengan tampilan baru.

Contoh ini mengilustrasikan bagaimana harus ada perilaku yang berbeda saat komponen dipasang dan saat komponen menerima alat peraga baru. Ini juga menunjukkan bagaimana alat peraga harus diperiksa untuk perubahan dalam kasus terakhir dan bagaimana fungsi tertentu harus dipanggil hanya pada perubahan penyangga tertentu.

Melihat ke belakang, pada dasarnya yang saya inginkan adalah fungsi yang hanya diperbarui ketika routeParams berubah. Namun, tidak perlu menambahkan fungsi lain karena kita dapat melakukan semua yang kita inginkan dengan fungsi yang ada, ditambah lagi kita tidak ingin memperumit siklus hidup.

Namun, sesuatu yang mungkin membantu di sini adalah lebih banyak dokumentasi tentang siklus hidup, contoh kerja, dll.

Terima kasih atas bantuan Anda. Tolong beritahu saya jika ada sesuatu yang aku salah di sini. Saya harap ini akan bermanfaat bagi siapa saja yang menemukan utas ini di masa depan.

@ shea256 contoh Anda sepertinya kasus yang masuk akal karena tidak memerlukan API baru dari kemampuan untuk mencapai apa yang Anda butuhkan tanpa sudut pandang API baru.

Saya menguraikan lebih banyak pemikiran di: https://Gist.github.com/jimfb/9ef9b46741efbb949744 , tapi saya masih merasa kita harus bisa merampingkan API untuk menulis lebih sedikit kode...

Bayangkan bahwa api memungkinkan Anda untuk menulis fungsionalitas yang sama, tetapi dengan boilerplate yang lebih sedikit:

class ProfilePage extends Component {
  static propTypes = {
    fetchCurrentProfile: PropTypes.func.isRequired,
    currentProfile: PropTypes.object.isRequired
  }
  state = {currentProfile: {}}; // not material to example (babel-stage-1)

  // called both on init and update
  willReceiveProps(nextProps) {
    if (!this.props || (this.props.routeParams.id !== nextProps.routeParams.id)
      nextProps.fetchCurrentProfile(nextProps.routeParams.id)
  }

  render() {
    var profile = this.props.currentProfile;
    return (
      <div>
        <h1>{ profile.name ? profile.name : null }</h1>
      </div>
    )
  }
}

Gagasan yang saya harap akan dipertimbangkan adalah mengurangi area permukaan API untuk mengurangi jumlah jalur kode dan pelat boiler. Saya bertanya-tanya apakah diskusi berlabuh pada permintaan awal untuk menambahkan sesuatu ketika mungkin melihatnya dari perspektif yang berbeda akan membuka jalur baru.

Ini hanyalah salah satu opsi (preferensi saya adalah acceptProps(prevProps) karena idealnya, hanya akan ada satu metode terkait prop di mana Anda dapat menggunakan this.props), tetapi bagian yang penting adalah bahwa ada satu jalur kode untuk inisialisasi komponen dan prop apa pun berubah daripada jalur kode berbeda yang kita miliki sekarang dengan tanda tangan API yang berbeda. Apapun solusi orang setuju untuk menjadi lebih baik.

Mendapatkan pengurangan boilerplate adalah apa yang saya harap dapat dicapai oleh masalah ini (untuk memperjelas kebutuhan/masalah saya!) metode siklus hidup secara signifikan, memperpendek nama metode sekarang karena ES6 tersedia secara luas dan Komponen tampaknya menjadi jalan ke depan, dll).

@akinnee-gl , memiliki aplikasi yang terdiri dari banyak komponen kecil jauh lebih baik daripada beberapa komponen berat karena beberapa alasan:

  1. Pendekatan ini berhubungan dengan "prinsip tanggung jawab tunggal"
  2. Anda dapat dengan jelas melihat komponen mana yang melakukan apa
  3. Anda dapat dengan mudah membuat fitur dan memperluas komponen dengan membungkus
  4. Metode dan properti tidak bertabrakan
  5. Lebih mudah untuk memperluas fitur karena satu komponen merangkum satu fitur

Mengenai pemberitahuan Anda bahwa membaca dari toko pada setiap render mungkin tidak efisien, saya telah membuat inti yang menunjukkan ide dasar bagaimana menerapkan komponen middleware untuk caching: https://Gist.github.com/me-andre/0ca8b80239cd4624e6fc

Saya telah mengambil kesempatan lain pada prinsip/sasaran yang dapat mengarah ke API yang ditingkatkan (semoga didasarkan pada metode alat peraga yang diterima seperti yang disarankan dalam masalah ini):

(A) menyederhanakan struktur kode / mengurangi boilerplate
(B) pisahkan props (input) dari state (internal)
(C) memungkinkan metode untuk mengontrol rendering komponen
(D) penyederhanaan penamaan metode berdasarkan asumsi subclassing Komponen
(E) kurangi jumlah metode props menjadi satu untuk inisialisasi dan perubahan
(F) metode props harus memiliki this.props dengan nilai terbaru

Ada klarifikasi tentang beberapa dari mereka di intinya.

@kmalakoff Sesuai intinya, jangan menambah ruang lingkup masalah ini. Masalahnya sudah cukup kompleks, dan mengalihkan percakapan ke dalam desain ulang API penuh tidak akan bisa dilacak. Anda dipersilakan untuk terus memikirkan masalah ini, tetapi harap pertahankan topik ini.

@kmalakoff Banyak poin yang Anda https://github.com/reactjs/react-future/issues/40#issuecomment -142442124 dan https://github.com/reactjs/react-future/issues/40#issuecomment - 153440651. Itulah thread-thread yang cocok untuk diskusi itu. Jika Anda mencari diskusi yang lebih umum/desain holistik/API, media yang tepat mungkin adalah https://discuss.reactjs.org/

@jimfb Saya telah memikirkan hal ini setelah Anda menyarankan agar saya memindahkan ini ke inti dan sebenarnya tidak percaya bahwa garis analisis ini di luar topik ... alasan saya tertarik dengan masalah ini seputar alat peraga yang diterima adalah karena saya percaya memiliki metode siklus hidup props yang diterima akan memungkinkan saya untuk mengurangi boilerplate.

Tolong dengarkan saya ... mengurangi boilerplate adalah masalah yang dapat diselesaikan oleh metode siklus hidup dalam masalah ini untuk saya.

Saya percaya itu juga bisa menjadi bagian penting dari alasan mengapa orang tertarik dengan metode siklus hidup ini karena API saat ini mendorong boilerplate lebih dari yang kita inginkan.

Karena itu, saya akan dengan senang hati mencoba memisahkan peningkatan API dan misalnya, hanya fokus pada penjelajahan ruang solusi seputar peningkatan API yang terkait dengan alat peraga dalam masalah ini.

@kmalakoff Topik utas ditentukan oleh judul dan posting pertama. Judulnya componentDidReceiveProps Please bukan lots of general ways to reduce boilerplate . Utas ini adalah tentang mengurangi boilerplate secara khusus melalui pengenalan metode siklus hidup yang sangat spesifik. Diskusi itu saja sudah cukup bernuansa, tanpa memperkenalkan topik tambahan (seperti mengganti nama semua fungsi) yang sudah dibahas di edisi lain.

Poin Anda sangat berharga, dan saya mendorong Anda untuk berdiskusi, harap pindahkan ke utas lain, karena kami ingin utas github tetap fokus pada topik yang ada. Jika tidak, diskusi terlalu sulit untuk dilacak/dikelola. Utas memang ada untuk sebagian besar topik yang Anda angkat.

@jimfb mengapa orang meminta componentDidReceiveProps ? Alasan saya tertarik adalah untuk mengurangi boilerplate yang berhubungan dengan props . Saya tidak yakin bagaimana menyatakan ini lebih jelas sehingga saya dapat didengar dan dipahami.

Anda telah menanyakan masalah dan kasus penggunaan, dan saya telah menyatakan ini sebagai masalah bagi saya dan menunjukkan kasus penggunaan di atas (menanggapi @ shea256) yang tampaknya sesuai topik, dalam ruang lingkup dan, dari sudut pandang saya, penting untuk diselesaikan masalah ini.

Saya telah setuju untuk menunda perluasan cakupan ke masalah/peningkatan API umum dan akan. Saya berjanji! :mengedip:

FYI: seperti yang saya nyatakan sebelumnya, alasan saya memulai eksperimen pemikiran seputar masalah ini adalah karena argumennya tampak sedikit terlalu terfokus (mis. kita sudah dapat melakukan semua yang kita butuhkan dengan API saat ini) daripada mengidentifikasi motivasi yang mendasari di balik isu. Seperti yang Anda ketahui, terkadang Anda perlu mundur, lalu fokus, lalu melihat dari sudut yang berbeda, lalu meninjau kembali asumsi, menyelidiki alasan di balik permintaan, dll. untuk beralih ke solusi terbaik untuk suatu masalah. Mudah-mudahan, saya telah membantu menarik perhatian untuk ini dan partisipasi saya akan membantu menyelesaikan masalah ini untuk kepuasan kami! (tentu saja, saya juga berharap React API akan berkembang menjadi lebih mudah digunakan dan akan melanjutkan diskusi itu di tempat lain... terima kasih atas tautannya)

@kmalakoff , ok, untuk mengurangi boilerplate Anda cukup membuat kelas atau komponen yang dapat digunakan kembali dari mana Anda mensubklasifikasikan atau membuat komponen lain. Tidak ada yang mencegah Anda mendefinisikan metode umum untuk semua komponen di aplikasi Anda. React memang memberikan perpanjangan yang sangat baik: Anda dapat mendefinisikan komponen sebagai objek, fungsi, atau kelas. Anda dapat memperluas komponen dengan membuat subklasifikasi, mixin, atau pabrik.

@me-andre yang benar-benar merupakan opsi jika masalah ini tidak mengarah pada peningkatan API.

Masalah ini diangkat untuk mendorong diskusi seputar keinginan untuk membuat perubahan pada API untuk meningkatkannya. Menjelajahi alternatif dalam kode klien secara definitif harus dipertimbangkan, tetapi jika kasus kuat dibuat bahwa API harus diubah, solusi semacam ini tidak diperlukan. Untuk melawan argumen, kasus juga perlu dibuat untuk apa API yang ditingkatkan seharusnya dan kemudian dievaluasi terhadap API saat ini untuk menilainya.

Misalnya, jika Anda ingin mendemonstrasikan bahwa API saat ini tanpa mendefinisikan superclass khusus dapat digunakan dengan cara untuk mengurangi boilerplate (mis. kami menggunakan API secara tidak benar, atau ada fitur di API saat ini yang dapat digunakan untuk mencapai tingkat pengurangan boilerplate yang serupa, dll) atau buktikan mengapa tidak ada peningkatan yang mungkin (mis. tidak ada solusi umum karena ada kasus penggunaan utama yang tidak dapat didukung dalam opsi peningkatan API kami), dll, Anda dapat membuat kasus bahwa API cukup baik apa adanya.

Jika API mengharuskan orang untuk menulis superclass khusus untuk pola aliran kontrol dasar dan umum, ini memperkuat argumen bahwa ada kemungkinan API harus ditingkatkan.

Penasaran - apa alasan untuk tidak memicu componentWillReceiveProps sebelum pemasangan? Jika Anda memikirkannya, komponen tersebut benar-benar menerima alat peraga saat diinisialisasi. Hanya saja tidak menerima alat peraga baru .

Apa kasus penggunaan di mana Anda hanya ingin memicu sesuatu setelah menerima alat peraga baru (dan bukan pada penerimaan penyangga awal)?

Saya mungkin kehilangan sesuatu yang jelas di sini tetapi hanya mencoba untuk mendamaikan sudut pandang dari berbagai pihak.

Bagaimanapun, jika componentWillReceiveNewProps penting dalam beberapa kasus, seseorang masih dapat mensimulasikannya dengan componentWillReceiveProps dimodifikasi dengan melakukan pemeriksaan pada props yang masuk.

@kmalakoff jika componentWillReceiveProps dipicu pertama kali, apakah itu memenuhi standar Anda untuk penyederhanaan API?

componentWillReceiveProps tidak terpicu di mount bukan alasan orang meminta componentDidReceiveProps . Orang-orang meminta componentDidReceiveProps karena mereka menulis semua metode mereka untuk mengakses this.props . Ketika componentWillReceiveProps dipanggil, nextProps dilewatkan, tetapi this.props belum berubah, artinya kita harus meneruskan nextProps ke semua metode yang dipanggil sebagai respons terhadap componentWillReceiveProps , alih-alih membiarkannya apa adanya. Kami berakhir dengan satu ton props = props || this.props dan satu ton melewati props ke dalam setiap fungsi yang kami panggil.

@ shea256 poin bagus. Memiliki jalur kode yang berbeda untuk inisialisasi vs perubahan adalah salah satu penyebab utama prop boilerplate. Akar penyebab lainnya adalah memiliki tanda tangan yang berbeda untuk menangani alat peraga seperti yang ditunjukkan oleh @akinnee-gl.

Inilah mengapa saya mencoba memperluas ruang solusi yang sedang dipertimbangkan (mis. juga memanggil init) karena sebenarnya ada solusi yang lebih baik untuk mengurangi prop boilerplate lebih banyak.

Semoga kita bisa melangkah lebih jauh:

Sebelum Kait Baru

componentWillMount() {
  this.setup(this.props.id);
}

componentWillReceiveProps(next) {
  this.setup(next.id);
}

setup(id) {
  UserActions.load(id);
}

Setelah Kait Baru (Revisi)

componentDidReceiveProps(prevProps) {
  UserActions.load(this.props.id);
}

atau jika UserActions.load tidak dapat memeriksa id yang sedang dimuat:

componentDidReceiveProps(prevProps) {
  if (!prevProps || (prevProps.id !== this.props.id))
    UserActions.load(this.props.id);
}

@kmalakoff , apa yang saya bicarakan adalah bahwa peningkatan API benar-benar tersedia untuk Anda saat ini: Anda dapat membuat pabrik komponen Anda sendiri dan kemudian berbagi dengan kami (bersama dengan contoh kasus penggunaan). Ini akan membuat proposal dan alasan Anda seratus kali lebih jelas. Karena semua titik siklus hidup sudah memiliki panggilan balik yang sesuai, Anda dapat memperkenalkan metode baru apa pun di titik siklus hidup/status komponen mana pun. Anda bahkan dapat mencampur emitor peristiwa ke dalam komponen Anda dan memungkinkan untuk melampirkan beberapa penangan untuk perubahan status.

@shea256 , salah satu alasan yang mungkin untuk componentWillReceiveProps tidak terpicu sebelum render pertama adalah bahwa tidak ada yang namanya this.props pada waktu itu. Apa yang biasa Anda lakukan di componentWillReceiveProps adalah membandingkan this.props[propName] dengan newProps[propName] . Memiliki metode yang dipicu sebelum render pertama akan membuat Anda juga harus memeriksa keberadaan this.props . Selain itu, seluruh komponen benar-benar tidak diinisialisasi pada saat menerima props sebelum render awal, bahkan tidak memiliki state .

@kmalakoff , saya telah dua kali memposting contoh kode yang menunjukkan cara mengatur komponen Bereaksi dengan cara yang tidak memerlukan setup atau peretasan serupa. Bisakah Anda memberi tahu mengapa Anda masih berusaha untuk mengubah perilaku komponen React alih-alih menyesuaikan kode Anda sehingga terintegrasi dengan React? Akan sangat bagus jika Anda hanya menunjukkan di mana sampel saya tidak sesuai untuk kasus penggunaan Anda.

@akinnee-gl , alasan untuk tidak memperkenalkan metode baru hanya untuk mengakses this.props pada pembaruan adalah karena kami memiliki metode seperti itu - disebut render() . Itu bahkan dipanggil setelah cek untuk shouldComponentUpdate() - yang biasanya merupakan tempat di mana Anda melakukan this.props !== newProps atau _.isEqual(this.props, newProps) dll.
Jika Anda merasa harus memiliki metode terpisah untuk beberapa pengaturan, mengapa tidak mensubklasifikasikan komponen React saja dan mendefinisikan metode render()

this.setup(this.props);
return this._render();

Saya hanya tidak mengerti bagaimana itu menyederhanakan hal-hal di ekosistem React, tetapi itulah yang terus Anda minta.

@me-andre premis masalah ini bukan karena kami tidak dapat mencapai apa yang kami inginkan dengan API saat ini atau kami tidak dapat mengatasi API saat ini dalam kode klien. Premis dari masalah ini adalah bahwa React API saat ini kurang optimal dan perlu ditingkatkan ; misalnya, jika Anda menemukan prinsip tentang tampilan API yang optimal (seperti yang saya coba di atas), React API saat ini akan mendapat skor dalam kisaran tingkat menengah karena suboptimal/kurang di sejumlah area.

Sayangnya, menyediakan cara dalam kode klien untuk mengatasi React API tidak mengatasi akar penyebab masalah, mengalihkan perdebatan dari mengatasi masalah yang mendasarinya, dan tidak akan mengarah pada perdebatan seputar solusi potensial untuk meningkatkan React API.

Singkatnya, saya sudah memiliki solusi yang bekerja untuk saya karena saya memiliki banyak aplikasi Bereaksi dalam produksi sehingga praktik terbaik bisa bagus untuk posting blog, tetapi menggunakannya sebagai garis perdebatan dalam masalah ini hanya akan mengalihkan kita dari perdebatan nyata tentang tujuan sebenarnya dari masalah ini: bagaimana meningkatkan React API (dalam masalah ini, terbatas pada kasus penggunaan prop dan boilerplate).

React 1.0 harus mengarah ke atas, bukan ke tengah. Peningkatan versi utama dapat merusak kompatibilitas mundur, jadi mari kita gunakan API terbaik berdasarkan apa yang telah kita pelajari selama bertahun-tahun menggunakan versi 0.x.

(FYI: Saya pikir orang mungkin tidak terlibat dengan contoh Anda sebanyak yang Anda harapkan karena mereka tidak datang ke sini untuk diajarkan tentang API saat ini, tetapi karena mereka mencari/mengharapkan peningkatan pada API, mis. dapat dianggap memiliki niat baik, tetapi sedikit tidak selaras)

Saya pikir orang mungkin tidak terlibat dengan contoh Anda sebanyak yang Anda harapkan karena mereka tidak datang ke sini untuk diajari tentang API saat ini, tetapi karena mereka mencari/mengharapkan peningkatan pada API

Oke, Anda datang dengan proposal peningkatan API, tetapi kemudian Anda menunjukkan kode yang terlalu jauh dari "Bereaksi praktik terbaik". Beberapa hal tampak sangat mirip dengan praktik terburuk. Kemudian Anda memberi tahu: "itulah alasan untuk perubahan". Ya, itulah alasan untuk perubahan tetapi tidak di basis kode Bereaksi.
Saya menunjukkan kepada Anda cara mengatur ulang kode agar berfungsi dengan baik dengan React tetapi abaikan saja tampilan penggunaan yang tepat dan tetap bersikeras. Itu sepertinya bukan debat yang konstruktif.

Sayangnya, menyediakan cara dalam kode klien untuk mengatasi React API tidak mengatasi akar penyebab masalah

Saat Anda menggabungkan API level rendah dengan API level lebih tinggi, itu bukan solusi, tetapi praktik umum. Banyak kerangka kerja brilian mengikuti ide itu.
Yang terus saya katakan adalah membungkus API jelek yang ada dengan apa yang ingin Anda gunakan dan bagikan dengan kami. Bersama dengan contoh penggunaan dan penjelasan mengapa itu menjadi lebih baik, itu akan luar biasa.
Sekali lagi, saya hanya tidak melihat alasan mengapa Anda tidak melakukannya saja. Karena jika apa yang Anda bicarakan adalah masalah umum, itu akan sangat membantu banyak orang.

Saya memiliki banyak aplikasi Bereaksi dalam produksi sehingga praktik terbaik bisa sangat bagus untuk posting blog, tetapi menggunakannya sebagai garis perdebatan dalam masalah ini hanya akan mengalihkan kita dari debat nyata

Apa yang biasa Anda lakukan ketika Anda merancang/mendesain API adalah memprediksi masalah, berhipotesis tentang kasus penggunaan, dll. Alasan mengapa orang berhipotesis bukanlah karena mereka mencoba mengabstraksikan diri mereka sendiri dari dunia nyata untuk mencari yang ideal. Ini hanya kurangnya pengalaman - Anda tidak bisa mendapatkan pengalaman "di muka".

Anda mengatakan bahwa Anda memiliki pengalaman itu, Anda telah melihat masalah nyata dan Anda memiliki beberapa solusi yang dapat Anda bagikan. Itulah tepatnya yang dapat mengubah debat ini menjadi "nyata" dan "efektif". React sendiri dibangun di atas masalah dan tantangan nyata - itulah mengapa ia memecahkan masalah arsitektur nyata dan bukan hanya "cara menulis hello world dalam 3 baris".

@ saya-andre Saya mendengar Anda dan garis argumen Anda jelas.

Anda benar bahwa inti dari argumen saya adalah bahwa jika kita menetapkan prinsip yang lebih baik berdasarkan pengalaman kolektif kita menggunakan React API saat ini dan membuka perdebatan untuk memasukkan solusi non-dogmatis yang dapat mengubah API dalam beberapa cara mendasar, kita dapat dan harus raih kesempatan untuk meningkatkan React API agar lebih baik dari sekarang. Jangan berpuas diri saat masih ada ruang untuk berkembang!

Bagaimana Anda menilai React API saat ini di sekitar alat peraga? (misalkan menggunakan nilai huruf: F ke A+), mengapa, dan apa yang akan Anda lakukan untuk memperbaikinya jika kurang dari A+?

@me-andre apakah Anda memiliki kesempatan untuk mempersiapkan peringkat dan analisis Anda? Saya tertarik untuk mendengar apa yang Anda yakini sebagai kekuatan, kelemahan, dan peluang dengan API saat ini.

+1

+1 Tolong

Apakah ada solusi? Saya membutuhkan ComponentDidReceiveProps

Saya membuat masalah ini lebih dari setahun yang lalu dan telah menggunakan React setiap hari sejak itu. Saya tidak lagi berpikir ada kasus penggunaan untuk componentDidReceiveProps yang membenarkan peningkatan API.

@AlexCppns apa yang Anda coba lakukan?

@iammerrick , sebenarnya tidak apa-apa, saya hanya salah paham bagaimana componentWillReceiveProps digunakan.

Saya mengalami ini beberapa kali, dan yang akhirnya saya lakukan adalah:

componentWillReceiveProps(nextProps) {
  if (this.props.foo !== nextProps.foo) this.needsUpdate = true;
}
componentDidUpdate() {
  if (this.needsUpdate) {
    this.needsUpdate = false;
    // update the dom
  }
}

Ini tidak terlalu buruk.

@brigand , tidak perlu bendera - Anda dapat membandingkan alat peraga dalam componentDidUpdate() :

componentDidUpdate(prevProps) {
    let needsUpdate = prevProps.foo !== this.props.foo;
    // ...whatever
}

Selain itu, solusi Anda dapat dengan mudah dipecahkan oleh shouldComponentUpdate() , yang dapat mencegah rendering ulang.

Oh keren, terima kasih!

@jimfb Saya pikir saya memiliki kasus penggunaan sinkron di bawah ini. Saya pikir componetDidReceiveProps sudah sempurna untuk ini.

  componentDidMount() {
    this._selectAll()
  }

  componentDidUpdate(prevProps) {
    let shouldUpdateSelected = (prevProps.recordTypeFilter !== this.props.recordTypeFilter) ||
      (prevProps.statusFilter !== this.props.statusFilter) ||
      (prevProps.list !== this.props.list)

    if (shouldUpdateSelected) { this._selectAll() }
  }

  _selectAll() {
    this.setState({ selectedIds: this._getFilteredOrders().map((order) => ( order.id )) })
  }

  _getFilteredOrders() {
    let filteredOrders = this.props.list

    // recordTypeFilter
    let recordTypeFilter = this.props.recordTypeFilter
    filteredOrders = _.filter(filteredOrders, (order) => {
        // somelogic
    })

    // statusFilter
    let statusFilter = this.props.statusFilter
    filteredOrders = _.filter(filteredOrders, (order) => {
        // somelogic
    })

    return filteredOrders
  }

@chanakasan , contoh Anda tidak memiliki metode render() yang penting untuk memahami contoh Anda dan menyarankan solusi yang lebih baik.
Kedua, kode Anda terhubung ke beberapa logika bisnis khusus dan tidak mudah dibaca. Jangan sungkan untuk menjelaskan, bukan sekedar membuang copy-paste ke orang lain.
Saya telah membaca contoh Anda, dan ingin berbagi pemikiran berikut:

  1. Ini adalah kasus penggunaan componentWillReceiveProps , bukan componentDidUpdate . Jika Anda beralih ke componentWillReceiveProps , komponen Anda akan merender ulang dua kali lebih sedikit sambil mempertahankan logika yang sama. Setelah setahun sejak saya meninggalkan diskusi ini, saya masih melihat nol kasus penggunaan untuk componentDidUpdate kecuali untuk bereaksi terhadap perubahan DOM.
  2. Jauh lebih baik, namun akan menghindari kait sama sekali dan memindahkan semua logika ke metode render() / bermigrasi ke komponen stateless, karena this.state.selectedIds sebenarnya bukan status. Ini murni dihitung dari alat peraga.

Hai @me-andre, Terima kasih telah meluangkan waktu untuk menjawab. Saya telah membaca diskusi di halaman ini dan saya ingin berterima kasih kepada Anda yang telah berpartisipasi di dalamnya.

Ya, componentDidReceiveProps tidak diperlukan, tetapi segala sesuatunya tampak misterius tanpanya.
Anda telah mengatakan your component would re-render twice as less jika saya menggunakan componentWillReceiveProps . Itu masih menjadi misteri bagiku.

Saya memang memikirkan dan mencoba dua hal yang Anda sarankan sebelumnya, tetapi gagal.

  1. componentWillReceiveProps tidak akan bekerja karena fungsi _getFilteredOrders() dipanggil dari _selectAll() membutuhkan newProps.
  2. Saya tidak bisa memikirkan cara untuk mendapatkan selectedIds tanpa menyimpannya dalam status.

Saya baru saja membuat contoh lengkap dari use case saya. Saya telah membuatnya mudah untuk dipahami sebanyak mungkin.

Jika Anda bisa, silakan lihat dan arahkan saya ke arah yang benar. Jika saya dapat memahami ini dengan benar, saya akan membagikan contoh ini di posting blog untuk membantu orang lain juga.

@chanakasan , ayolah, ini terlihat seperti kode produksi. Saya tidak akan membaca semuanya dan membantu proyek Anda secara gratis.

Namun saya dapat mengarahkan Anda ke arah yang benar:

  1. Baik componentWillReceiveProps() dan componentDidUpdate() dapat mengakses props sebelumnya dan selanjutnya. Itu jelas terlihat dari dokumen resmi React.
  2. Dari copypaste lengkap kode Anda, sekarang jelas bahwa Anda menggunakan status untuk menyimpan id terpilih yang dapat dialihkan oleh pengguna. Tidak apa-apa menggunakan status saat itu, tetapi tetap saja componentWillReceiveProps() akan memicu rendering ulang dua kali lebih sedikit. (karena render akan terjadi setelah componentWillReceiveProps() , setState() hanya akan memperbarui status untuk render yang akan datang).
  3. Silakan lihat di dokumen . Hemat waktu Anda dan hormati orang lain.

@me-andre Saya pikir saya mengerti maksud Anda tentang componentWillReceiveProps menggunakan baris ini di dokumen:

componentWillReceiveProps() tidak dipanggil jika Anda hanya memanggil this.setState()

Tetapi peringatan menggunakan componentWillReceiveProps adalah saya harus meneruskan nextProps ke fungsi.

Saya akan mencoba mengikuti saran Anda. Terima kasih saya menghargainya.

Btw, saya tidak bermaksud agar Anda membantu proyek produksi saya secara gratis :). Ini adalah contoh yang lebih lengkap dari contoh singkat saya sebelumnya untuk mengisi kekosongan tentang kasus penggunaan saya.

bagaimana jika kita menggunakan ini bersama dengan shouldComponentUpdate?
di mana kami tidak ingin memperbarui status komponen atau merender,
tapi kami membutuhkan this.props untuk menggunakan props terbaru untuk melakukan beberapa pekerjaan skrip manual setelah props diterima

pekerjaan saya adalah mengatur this.props ke props baru sebelum menjalankan fungsi yang diinginkan

Akan sangat menyenangkan memiliki ComponentDidMount atau pengait untuk itu. Mengapa? Karena, terkadang, kita perlu melakukan perhitungan lain yang tidak bergantung pada siklus hidup React.

Misalnya: Saya memiliki komponen induk yang dapat diubah ukurannya. Komponen anak bertanggung jawab untuk merender peta OpenLayer yang memiliki fungsi yang bertanggung jawab untuk mengubah ukuran peta. Namun, itu harus terjadi setelah anak mendapatkan alat peraga dari orang tua dan juga melakukan perhitungan lain dalam siklus hidup React.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat