React: Bagaimana cara mengimplementasikan shouldComponentUpdate dengan this.context?

Dibuat pada 13 Nov 2014  ·  126Komentar  ·  Sumber: facebook/react

Saya tahu this.context tidak secara resmi ada di sana tetapi beberapa perpustakaan mengandalkannya, dan sepertinya itu menjadi bentuknya dengan # 2509.

Saya mencoba untuk memahami bagaimana tepatnya shouldComponentUpdate seharusnya diimplementasikan dengan context dalam pikiran. Saya perhatikan itu menerima argumen ketiga ( nextContext ) dan saya dapat memperpanjang PureRenderMixin untuk juga memeriksanya:

  shouldComponentUpdate: function(nextProps, nextState, nextContext) {
    return !shallowEqual(this.props, nextProps) ||
           !shallowEqual(this.state, nextState) ||
           !shallowEqual(this.context, nextContext); // this will throw without context, read on
  }

Komponen yang tidak memilih this.context dengan tidak menghilangkan contextTypes tidak akan mendapatkan argumen ketiga ini, yang dapat dimengerti.

Namun ini menjadi masalah ketika kita memiliki komponen <Middle /> di antara <Top /> pemilik konteks dan <Bottom /> konsumen konteks. Jika <Middle /> mengimplementasikan batasan shouldComponentUpdate , tidak ada cara bagi <Bottom /> untuk bereaksi terhadap pembaruan konteks <Top /> sama sekali:

( biola )

var Bottom = React.createClass({
  contextTypes: {
    number: React.PropTypes.number.isRequired
  },

  render: function () {
    return <h1>{this.context.number}</h1>
  }
});

var Middle = React.createClass({
  shouldComponentUpdate: function (nextProps, nextState, nextContext) {
    return false;
  },

  render: function () {
    return <Bottom />;
  }
});

var Top = React.createClass({
  childContextTypes: {
    number: React.PropTypes.number.isRequired
  },

  getInitialState: function () {
    return { number: 0 };
  },

  getChildContext: function () {
    return { number: this.state.number };
  },

  componentDidMount: function () {
    setInterval(function () {
      this.setState({
        number: this.state.number + 1
      });
    }.bind(this), 1000);
  },

  render: function() {
    return <Middle />;    
  }
});

React.render(<Top />, document.body);

Masalah yang sama akan terjadi jika saya mencoba memberikan Middle kesadaran konteks umum shouldComponentUpdate seperti yang saya tulis di atas, karena Middle tidak memiliki this.context kecuali jika memilih di.

Hal ini dimungkinkan untuk diselesaikan dengan menambahkan contextTypes ke Middle , tetapi tampaknya ini bukan solusi yang baik. Anda perlu secara eksplisit menambahkan contextTypes pada setiap level dengan shouldComponentUpdate pintar sehingga terlalu mudah untuk tergelincir.

Apakah ini akan diselesaikan dengan # 2112? Apakah ada solusi lain untuk saat ini? Apa cara yang direkomendasikan?

Component API Bug

Komentar yang paling membantu

Saya ingin tahu apakah propagasi konteks dapat terjadi di penjelajahan pohon terpisah, tanpa diblokir oleh shouldComponentUpdate palsu di tengah?

Pada dasarnya, ketika konteks induk berubah, ia harus menandai semua turunannya yang menerima konteks ini sebagai kotor, tidak peduli seberapa jauh. Perubahan konteks leluhur harus memiliki efek yang sama seperti perubahan keadaan untuk keturunan yang memilih konteks ini — mereka harus menerima context terlepas dari apa yang dikatakan orang tua mereka.

Semua 126 komentar

Ini adalah pertanyaan yang sangat bagus. Terima kasih telah membesarkannya!

Ini adalah kasus saat Anda memangkas / mengoptimalkan penghitungan ulang pohon secara manual. Menurut saya, Anda perlu meminta akses ke variabel konteks apa pun yang relevan dengan perhitungan Anda. Kami juga dapat mempertimbangkan untuk melakukan hal-hal mewah lainnya seperti meneruskan dalam hash dari konteks lengkap (atau bahkan konteks lengkap) jika perlu.

@sebmarkbage - pikiran?

Ya, masalahnya adalah komponen tengah tidak tahu konteks apa yang mungkin dibutuhkan oleh beberapa anak jauh. Tidak mungkin mereka tahu contextTypes harus dideklarasikan bahkan _beable_ untuk mengimplementasikan shouldComponentUpdate .

Saya ingin tahu apakah propagasi konteks dapat terjadi di penjelajahan pohon terpisah, tanpa diblokir oleh shouldComponentUpdate palsu di tengah?

Pada dasarnya, ketika konteks induk berubah, ia harus menandai semua turunannya yang menerima konteks ini sebagai kotor, tidak peduli seberapa jauh. Perubahan konteks leluhur harus memiliki efek yang sama seperti perubahan keadaan untuk keturunan yang memilih konteks ini — mereka harus menerima context terlepas dari apa yang dikatakan orang tua mereka.

@gaearon Saya pikir dalam hal ini Anda perlu merender ulang semuanya dan shouldComponentUpdate tidak akan memiliki efek pemangkasan subpohon. Jika tidak, konteks akan menjadi tidak konsisten dengan pohon elemen.

@bayu_joo

Saya pikir shouldComponentUpdate pada komponen tengah seharusnya tidak berpengaruh pada apakah keturunan mereka menerima konteks baru, sama seperti itu tidak berpengaruh pada apakah mereka menerima status baru:

http://jsbin.com/geseduneso/2/edit?js , keluaran

(Jika ini masalahnya, kedua angka akan bertambah)

Dimana ketidakkonsistenannya?

Dengan kata lain, saya pikir context harus bekerja sama persis seperti jika pemilik konteks memiliki sesuatu seperti "toko" yang hasilnya getChildContext() ditulis dalam componentWillUpdate , dan semua konsumen konteks turunan yang mendeklarasikan kunci dari konteks itu di contextTypes , harus menerima konteks itu seolah-olah mereka berlangganan ke "toko" itu dan memperbarui status mereka sendiri.

Yang saya maksud bukan implementasi sebenarnya — tetapi saya ingin menunjukkan bahwa model ini tidak lebih tidak konsisten daripada aplikasi Flux mana pun dengan shouldComponentUpdate di tengahnya. Konteks harus bertindak seperti "penyimpanan samping", tetapi dibatasi oleh subtree.

Edit: ini tidak akan berfungsi karena orang tua dapat berubah

Saya berbicara dengan Glenjamin di IRC dan dia meyakinkan saya mengubah konteks mungkin ide yang buruk. Anda kehilangan kemampuan untuk alasan mengapa sesuatu diperbarui jika beberapa pembaruan root secara implisit menyebabkan pembaruan anak yang berbeda.

Tapi kemudian, satu-satunya solusi yang masuk akal yang saya lihat adalah dengan sepenuhnya melarang perubahan konteks. Artinya, buat getChildContext() mirip dengan getInitialState() , yang hanya dipanggil sekali sebelum komponen dipasang.

Ini akan membuat konteks jauh lebih sederhana untuk dipikirkan. Kita dapat menghapus parameter ketiga dari shouldComponentUpdate karena konteks tidak pernah diperbarui.

Jika Anda _membutuhkan_ pembaruan dari pemilik konteks (mis. Seperti react-router ingin activeRoutes diteruskan dari atas ke bawah untuk digunakan di ActiveState mixin cc @mjackson), tidak ada yang menghalangi Anda untuk meneruskan { addChangeListener, removeChangeListener, getActiveRoutes } di context . Keturunan sekarang dapat berlangganan perubahan dan memasukkannya ke state .

Apakah ini solusi yang masuk akal?

Saya pikir pertanyaan kunci untuk dijawab adalah:

Dalam skenario apa melewati _data_ melalui context lebih baik daripada meneruskan data melalui props atau memicu kejadian untuk membuat pemanggilan komponen miliknya setState .

Saya telah menggunakan konteks untuk melewatkan referensi objek dengan cukup senang, karena saya hanya menulis ke objek tersebut, bukan membaca. misalnya. this.context.triggerAction("something")

Kasus penggunaan untuk konteks adalah untuk parameter yang dapat diterapkan di subpohon yang berpotensi besar, tetapi Anda tidak ingin melewati node penampung yang lebih umum. Contohnya mungkin tema warna, di mana sejumlah besar node mungkin mendengarkan untuk melihat apakah warna latar belakang seharusnya putih atau hitam; Anda tidak ingin menyebarkannya ke mana-mana sebagai parameter.

Membuat getChildContext () berperilaku lebih seperti getInitialState () tidak akan benar-benar menyelesaikan masalah, karena Anda selalu bisa mengganti simpul induk yang menyediakan nilai konteks tertentu dengan simpul induk lain yang menyediakan nilai konteks berbeda. Untuk subpohon yang terpengaruh, hal ini tidak dapat dibedakan dari mutasi nilai variabel konteks.

Saya pikir kita dapat menemukan solusi yang menghindari pengguna memasang pendengar perubahan.

Saya pikir @andreypopp mungkin benar. Atau paling tidak, kita perlu menyediakan cara agar shouldComponentUpdate mengetahui apakah ada sesuatu dalam konteks yang berubah, sehingga dapat memutuskan untuk selalu mengembalikan nilai benar jika ada perubahan variabel konteks.

Saya akan mengobrol dengan @sebmarkbage hari ini dan melihat apa yang dia pikirkan.

Membuat getChildContext () berperilaku lebih seperti getInitialState () tidak akan benar-benar menyelesaikan masalah, karena Anda selalu bisa mengganti simpul induk yang menyediakan nilai konteks tertentu dengan simpul induk lain yang menyediakan nilai konteks berbeda. Untuk subpohon yang terpengaruh, hal ini tidak dapat dibedakan dari mutasi nilai variabel konteks.

Aduh. Anda benar sekali, saya belum mempertimbangkan ini.

@jsfb Setelah

Saat ini, ya, itu akan dipasang kembali, tetapi itu sebagian merupakan detail implementasi. Anda dapat membayangkan (dan kami telah membahas implementasi dan konsekuensi dari) reparenting subpohon tanpa kehilangan status node.

@sebmarkbage dan saya mengobrol, dan sampai pada kesimpulan berikut:

  • shouldComponentUpdate adalah jalan keluar yang kompleks, yang implementasinya mengharuskan Anda memiliki pemahaman yang kuat tentang apa yang terjadi di bawah komponen. Untuk alasan ini, tidak masuk akal untuk menganggap Anda tahu variabel konteks mana yang digunakan, karena Anda sudah perlu mengetahui properti mana yang digunakan dan bagaimana mereka digunakan.
  • Perubahan ini mungkin tidak membuat situasi menjadi jauh lebih buruk daripada sebelumnya, dan ini merupakan perbaikan dari penggunaan hubungan "pemilik" yang lama. Oleh karena itu, masalah ini masih layak untuk didiskusikan, tetapi mungkin tidak menghalangi.
  • Konteks adalah fitur / eksperimen yang kompleks pada saat ini, dan kami mungkin perlu berpikir lebih keras sebelum secara resmi mendukung / mendokumentasikannya. Saat kita mempelajari lebih lanjut, kita mungkin akan terus mengulang topik ini.

@sebmarkbage , beri tahu saya jika saya melewatkan sesuatu!

Diskusi yang bagus! Terima kasih atas semua masukannya!

Terima kasih telah meluangkan waktu untuk membahas ini!

bukan tidak masuk akal untuk menganggap Anda tahu variabel konteks mana yang digunakan, karena Anda sudah perlu mengetahui properti mana yang digunakan dan bagaimana mereka digunakan.

Jika komponen Feed level teratas mengimplementasikan shouldComponentUpdate dengan menggunakan PureRenderMixin untuk menghindari pembaruan tambahan, itu tidak berarti bahwa Feed tahu bahwa di suatu tempat di dalamnya ada adalah Cell yang kebetulan berisi Link yang bergantung pada konteks router.

Ini menjadi lebih buruk ketika kerangka kerja (seperti kerangka perutean React paling populer ) menggunakan konteks dan Anda bahkan mungkin tidak menyadarinya. Di suatu tempat, ada aplikasi yang tidak mengubah status tautan aktif karena seseorang mengoptimalkan komponen tingkat atas dan secara harfiah _tidak tahu_ mereka harus mendeklarasikan contextTypes hingga _bahkan mendapatkan_ nextContext dalam shouldComponentUpdate .

Tidak mungkin komponen mengetahui _ semua kemungkinan turunannya_. Pada dasarnya, jika saya memindahkan komponen yang bergantung pada konteks di mana saja di dalam komponen yang mendukung PureRenderMixin , itu akan rusak tetapi sangat halus. Oleh karena itu, jika Anda menggunakan konteks, satu-satunya cara untuk menghindari kerusakan halus pada komponen yang tidak terkait ini adalah dengan _never_ mengimplementasikan shouldComponentUpdate yang bertentangan dengan apa yang dikatakan React tentangnya.

Beberapa kerangka kerja di atas React, seperti Om @swannodette , menghasilkan PureRenderMixin -ish shouldComponentUpdate _default_, aneh rasanya memotongnya seperti itu. Itu berarti pemecah konteks shouldComponentUpdate di setiap komponen untuk mereka.

Saya setuju ini tidak memblokir pekerjaan Anda, tetapi saya tidak setuju bahwa situasi saat ini memuaskan jika konteks akan digunakan sama sekali. Ini bukan hanya _hard_ untuk mengimplementasikan shouldComponentUpdate dengan konteks sekarang — ini benar-benar tidak mungkin kecuali kita membuat asumsi bahwa setiap komponen selalu menyadari apa yang bisa menjadi children .

Perpustakaan populer sudah sangat bergantung pada konteks. Saya mengerti itu bukan fitur yang didukung, tetapi menurut saya itu harus setidaknya _possible_ untuk membuatnya berfungsi dengan shouldComponentUpdate , atau harus dinonaktifkan, dan perpustakaan harus dipaksa untuk tidak menggunakannya, karena itu rusak secara halus.

Ini telah diketahui sejak awal dengan konteks yang diperkenalkan. Kami harus dapat memiliki fitur yang tidak terdokumentasi dan tidak didukung sebagai fitur eksperimental agar dapat mengulanginya untuk menemukan kasus khusus. Misalnya, jika kami tidak memiliki konteks, kami tidak akan tahu bahwa konteks tersebut perlu diubah menjadi berbasis kontainer, bukan berbasis pemilik. Kerusakan halus adalah bagian dari kontrak penggunaan fitur tidak berdokumen.

Saya pikir yang perlu kita lakukan adalah melewati shouldComponentUpdate jika ada konteks baru di mana saja di pohon induk. Kemungkinan dengan shouldUpdateChildContext atau sesuatu yang menentukan apakah seluruh subpohon perlu direkonsiliasi.

@bayu_joo

Saya kira ini bisa berhasil karena konteks hampir tidak dimaksudkan untuk sering berubah.
Dalam kasus ini, shouldComponentUpdate tidak membutuhkan parameter ketiga, bukan?

Benar, itu selalu tidak berguna.

Saya pikir yang perlu kita lakukan adalah by-pass shouldComponentUpdate jika ada konteks baru di mana saja di pohon induk.

Ini sangat masuk akal. Perubahan konteks pada induk perlu menimpa shouldComponentUpdate s yang salah di subtree.

Tapi itu menimbulkan pertanyaan: bagaimana kita tahu kapan konteks berubah? Untuk negara bagian dan properti kami memiliki setState dan render / setProps . Sepertinya kita perlu menyimpan salinan konteks saat ini di suatu tempat dan membedakannya dengan hasil dari getChildContext setiap kali render dipanggil.

Saya menggunakan konteks sebagai cara mengelola referensi toko. Saya suka ini karena saya dapat secara eksplisit mendefinisikan penyimpanan apa yang diperlukan, jadi
1) Saya dapat meniru data sampel hanya di toko yang saya perlukan untuk menguji sebuah komponen, menghindari keharusan membuat contoh kerangka kerja saya yang lebih besar, dan
2) meneruskan penyimpanan hanya-baca sederhana dengan data yang diketahui untuk rendering sisi server, yang menyederhanakan kasus sisi server karena sebagian besar kode aplikasi tidak digunakan.

Jadi, lihat contoh,

Dengan implementasi saya, data penyimpanan hanya diakses melalui getter. Elemen saya tidak menyimpan data cache. Saya ingin satu versi kebenaran. Sebagai contoh non-async sederhana, render () saya biasanya akan memiliki sesuatu seperti

var peopleStore = this.context.peopleStore;
var person = peopleStore.get(this.props.personId);
return <div>person.fullName</div>;

Komponen menghubungkan pendengar ke toko. Saya belum sepenuhnya memutuskan perinciannya. Semua toko memiliki acara onChange. Namun, saya belum memutuskan dua hal lainnya,
1) pendengar untuk perubahan properti individu
2) jika toko harus berisi toko

Dalam contoh ini, jika "orang" adalah "pengguna fb", itu adalah penyimpanan asinkron besar yang kompleks. Haruskah saya menggunakan kembali struktur toko untuk PersonStore? Satu untuk koleksi umum (getFriends, getPerson, dll) tetapi banyak contoh unik dari tipe toko Person untuk individu individu.

Jadi dalam contoh saya, Komponen saya memerlukan toko Orang sebagai parameter konteks. Kemudian menggunakan prop personId untuk mengidentifikasi dan berlangganan toko Person tertentu.

Sekarang, untuk memperkenalkan beberapa perubahan dinamis. Misalkan pengguna yang saat ini masuk log keluar dan orang lain masuk. Mengabaikan fakta bahwa Anda mungkin akan mengarahkan / menyegarkan halaman dalam aplikasi nyata, bagaimana elemen ini akan diperbarui? Mari asumsikan juga bahwa elemen ini masih ada di halaman dan tidak dihancurkan begitu saja.

Saya mengharapkan logika aplikasi untuk terlebih dahulu menghapus / menghancurkan toko People yang ada. Untuk itu, komponen saya perlu berhenti mendengarkan pembaruan. Untuk ini, saya akan merekomendasikan API ReactClass. Misalnya,

onContextChange (sebelumnya, baru)

Elemen tersebut kemudian dapat membandingkan dua instance peopleStore. Mari kita abaikan data publik dan asumsikan PeopleStore baru adalah null. Elemen akan berhenti berlangganan dari Store sebelumnya dan memicu render (). Render kemudian akan menampilkan beberapa jenis pesan 'pengguna tidak diketahui'.

Saat pengguna masuk sebagai pengguna lain, Store baru dibuat, elemen dipasang kembali, dan render () melakukan tugasnya dengan data baru.

Di belakang layar, "this.render ()" tidak bisa sinkron. Untuk setiap desain / contoh saya agar masuk akal sama sekali, panggilan render () perlu dikumpulkan oleh kerangka kerja dan digabungkan bersama.

Tidak seperti props, mendengarkan toko berada di luar peran inti React dalam mengelola rendering. Itu sebabnya saya tidak berpikir perubahan konteks harus dilibatkan dalam shouldComponentUpdate (). Dan meskipun contoh saya termasuk mengubah nilai konteks (objek toko baru), menurut saya toko tidak akan menjadi tidak berubah dalam sifat tingkat tinggi mereka. Menurut saya, desain aplikasi fluks yang khas akan beroperasi dengan model pelanggan, callback untuk async, dll. Objek penyimpanan dasar biasanya akan hidup selama masa pakai aplikasi.

Ada cukup banyak minat dalam hal ini. (Lihat referensi di atas.)

Ya @gaun .

Saya ingin meneruskan data pelokalan dalam konteks, dan membiarkan pengguna dapat mengubah bahasanya saat runtime, membiarkan semua komponen merender ulang sendiri dengan terjemahan yang diperbarui, mata uang, format tanggal ... Sejauh yang saya mengerti, ini tampaknya sulit dilakukan untuk saat ini.

Lihat juga
https://github.com/yahoo/react-intl/issues/58
https://github.com/facebook/react/issues/3038

@slorber Saya juga mengadopsi kustom PureRenderMixin , itu jelas bisa rusak dengan lebih ketat shouldComponentUpdate s di tengah, seperti yang dikatakan @gaearon (atau jika parameter ketiga akan hilang). Namun, Anda selalu dapat mengandalkan alat peraga. Mari kita lihat bagaimana masalah ini akan berkembang :)

@gpbl periksa itu:
https://github.com/facebook/react/issues/3038#issuecomment -76449195

Tampaknya bagi saya bahwa jika kita ingin merender ulang seluruh aplikasi dari atas jika terjadi perubahan konteks, kita dapat melepas dan memasang kembali node dalam centang loop peristiwa yang sama, dan itu tidak menghasilkan efek berkedip (terus-menerus). Ini adalah solusi yang sempurna untuk menangani perubahan bahasa pengguna.

@slorber Memanggil unmountComponentAtNode membuat pengalaman pengguna yang buruk, karena menyebabkan hilangnya semua status lokal.

Saya pikir inilah saatnya untuk menyatakan konteks sebagai fitur resmi. Tidak menggunakan konteks bukanlah pilihan bagi kebanyakan orang, karena router dan ReactIntl ​​menggunakannya.

@cody dkk, Untuk memperjelas: Konteks masih dapat berubah. Kami masih bereksperimen dengannya, dan tetap menyarankan untuk menghindarinya sampai kami memutuskan API final. Risiko penggunaan Anda sendiri. Apakah itu berguna: mungkin. Apakah sudah siap: tidak.

@cody ini bukan masalah untuk kehilangan status lokal bagi saya, karena saya tidak memiliki status lokal dan seluruh aplikasi saya mengelola status tidak berubah murni di luar React :) Periksa video yang telah saya lakukan untuk kerangka kerja: https: / /github.com/stample/atom-react

Saya pikir yang perlu kita lakukan adalah by-pass shouldComponentUpdate jika ada konteks baru di mana saja di pohon induk. Berpotensi dengan shouldUpdateChildContext atau sesuatu yang menentukan apakah seluruh subpohon perlu direkonsiliasi.

Ya, shouldUpdateChildContext membuatnya bagus dan simetris.

Adakah peluang untuk ini masuk ke 0,14?

Jika Anda mendesain API yang bagus dan menerapkannya. :)

Ini harus mencakup beberapa cara untuk menentukan bahwa hanya anak-anak yang mendengarkan kunci konteks yang benar-benar berubah yang benar-benar diperbarui. Dari pada segalanya.

Kecil kemungkinan tim inti penuh waktu kita sendiri akan punya waktu untuk itu. :(

Pada 9 Apr 2015, pukul 13.32, Dan Abramov [email protected] menulis:

Adakah peluang untuk ini masuk ke 0,14?

-
Balas email ini secara langsung atau lihat di GitHub.

Oke, saya akan lihat!

Maaf teman-teman, saya masih tidak punya waktu untuk mulai mengerjakan ini. Setelah rilis React DnD 1.0 yang tertunda, saya akan sibuk mempersiapkan konfirmasinya, jadi sangat tidak mungkin saya dapat mengerjakan ini dalam waktu dekat. :-(

@gaearon Ada rencana untuk melihat ini segera? Saya tertarik untuk melompat ke dalam ini karena tampaknya ini adalah salah satu bagian terakhir dari membuat konteks sepenuhnya dapat digunakan. (mungkin ada hal lain yang saya lewatkan?)

Satu hal yang saya ingin tahu adalah apakah pernyataan berikut ini benar atau tidak:

Konteks anak komponen harus _selalu_ merupakan pengurangan dari props & konteks statusnya

Ini memastikan kami dapat mengalirkan data dengan andal dalam siklus hidup yang diketahui. Ini mirip dengan pernyataan bahwa "render komponen selalu merupakan pengurangan status & alat peraga".

Ini adalah bagaimana saya saat ini membayangkannya - akan bagus untuk melihat apakah saya benar-benar keluar jalur !:

shouldUpdateChildContext menentukan apakah sub pohon harus diperbarui dengan konteks baru. Bagian dari siklus hidup ini dipicu oleh perubahan pada props atau konteks status komponen.

shouldComponentUpdate tetap dengan 3 parameter sehingga komponen dalam sub pohon yang disebutkan di atas dapat memutuskan apakah ia benar-benar harus memperbarui sesuatu (catatan: mengembalikan false di sini TIDAK mempengaruhi konteks yang mengalir ke sub pohon lebih jauh)

Hal lain yang saya ingin tahu di sini adalah apakah harus ada metode siklus hidup baru componentWillReceiveContext ? - Disebut pada saat yang sama dengan componentWillReceiveProps tetapi dalam aliran data konteks. Di sini memungkinkan untuk memanggil kedua metode ini pada "waktu yang sama".

@Tokopedia

Silakan melompatinya! Saya terlalu sibuk dengan hal-hal lain saat ini.

Ini memastikan kami dapat mengalirkan data dengan andal dalam siklus hidup yang diketahui.

Juga perlu diingat ada observe hook yang mungkin atau mungkin tidak dapat diimplementasikan di 0.14. Yang berarti mungkin ada atau mungkin tidak akan diturunkan data / observed / apapun namanya. Tapi itu mungkin tidak relevan dengan tugas Anda untuk saat ini.

Mendapat draf yang paling awal dari ini di garpu saya dan Anda dapat melihatnya berjalan pada examples/context/index.html

Saya telah menyiapkan hubungan "orang tua konteks" / "anak konteks" sederhana. Sebuah "konteks induk" adalah setiap komponen yang mungkin mengubah konteks anaknya (mis. Mengimplementasikan childContextTypes ) dan "anak konteks" adalah komponen apapun yang bergantung pada konteks atau mungkin mengubah konteks anaknya (mis. Mengimplementasikan contextTypes atau childContextTypes ). Hubungan ini diatur ketika komponen dipasang saat ini.

Saat siklus hidup pembaruan komponen mulai berlaku, kami memiliki dua kasus:

  1. Jika komponen mengatakan do _not_ update (Ie. shouldComponentUpdate() === false ) maka kami memeriksa apakah kami harus memperbarui konteks anak dengan shouldUpdateChildContext . Jika ini adalah true (default) maka jika komponen ini memiliki "anak konteks" langsung, kita mentransisikan komponen anak ke dalam siklus hidup pembaruan. Ini berlanjut sampai kita sampai ke akhir pohon konteks atau kita menemukan shouldUpdateChildContext() === false
  2. Jika sebuah komponen mengatakan lakukan pembaruan maka tidak ada yang berbeda. Tidak ada penyaluran data konteks samping dalam kasus ini dan kami membiarkan aliran normal berlanjut hingga komponen dapat mencapai kasus # 1 lagi.

Tidak diragukan lagi saya telah melewatkan beberapa hal penting jadi jika ada yang bisa melihat sekilas itu akan bagus. Menyambut komentar tentang arsitektur konteks serta penulisan kode yang sebenarnya agar sesuai dengan basis kode React! :)

Untuk contoh psuedo cepat pertimbangkan hal berikut:

<Root num={1}>  // Gives context {num: this.props.num}
  <Mid>         // Ignores any context and shouldComponentUpdate() === false
    <Child>     // Requires context {num: propTypes.number}

Untuk rendering awal (pemasangan) semuanya seperti yang kita harapkan. (Impl. Detail: hubungan orang tua / anak dibuat antara Root & Child )

Kami memperbarui Root agar memiliki nilai num prop dari 2

<Root num={2} />

Mid juga menerapkan metode shouldComponentUpdate() yang mengembalikan false karena metode render() tidak peduli tentang context.num dan tidak ada yang berubah - jadi mengapa harus diperbarui?

Di sinilah dalam kasus lama komponen Child tidak akan pernah melihat konteks baru karena kami telah menebus pembaruan di bawah pohon.

Dengan perubahan ini kita sekarang memeriksa metode shouldUpdateChildContext() pada Mid yang dapat (kita membiarkan tindakan default terjadi dalam contoh kita) melakukan pemeriksaan kesetaraan sederhana untuk melihat apakah ada nilai konteks berubah. Catatan: tanda tangan shouldUpdateChildContext() saat ini identik dengan shouldComponentUpdate() .

Jika shouldUpdateChildContext() adalah true (secara default) maka kami memperbarui setiap 'anak konteks' terdekat kami (hanya Child dalam contoh kasus) jika ada hubungan yang diatur sebelumnya . Ini akan menempatkan komponen itu ke dalam siklus hidup pembaruannya (berlawanan dengan diskusi yang saya lihat sebelumnya, ini akan _still_ memanggil shouldComponentUpdate() seperti biasa dengan konteks _new_ sebagai parameter ketiga karena ini menyediakan komponen dengan kontrol granular yang masih berakhir ketika diinginkan memperbarui).

Mudah-mudahan itu menjelaskan prosesnya dengan cukup baik!

@Chrisui Keren, senang melihat kemajuan dalam hal ini! Kita juga harus menambahkan banyak unit test ke fungsi dasar pemeriksaan kewarasan. Minimal:

  • Verifikasi pembaruan anak bahkan jika induk shouldComponentUpdate() mengembalikan false.
  • Verifikasi pembaruan anak bahkan jika induk shouldUpdateChildContext() mengembalikan false.
  • Pastikan anak tidak memperbarui jika komponen shouldUpdateChildContext() mengembalikan false.

Selain itu, jika ini adalah fitur yang didukung, kami mungkin ingin memverifikasi:

  • Verifikasi shouldUpdateChildContext() tidak dipanggil jika kakek nenek mengubah konteks yang disediakan, tetapi orang tua langsung menimpa konteks itu dan tidak berubah.
  • Verifikasi shouldUpdateChildContext() tidak dipanggil jika komponen tidak membaca dari variabel konteks yang berubah.
  • Verifikasi bahwa jika prop berubah dan variabel konteks berubah, kami tidak memperbarui / membuat dua kali.

cc: @sebmarkbage untuk mendapatkan masukan tentang desain / ide API.

@Chrisui Sejauh ini kedengarannya fantastis, terima kasih telah melakukan pekerjaan ini.

@jimfb Pasti akan mulai mendapatkan beberapa tes unit - hanya ingin memiliki sesuatu untuk dimainkan dan mengkonfirmasi bagaimana kita semua berpikir itu harus bekerja sebelum itu!

Mengenai rangkaian kasus kedua, ini adalah area yang telah saya hindari demi desain yang lebih sederhana. Misalnya, disarankan agar kita melihat untuk melihat kunci konteks tertentu mana yang diubah dan hanya memperbaruinya. Saya merasa ini mungkin menambah terlalu banyak kerumitan pada hubungan orang tua / anak saat ini dan akan kurang simetris dengan bagaimana data lain mengalir melalui React. Sebagai contoh (saya mungkin sangat naif dan mengabaikan ini) kami tidak membandingkan mengubah alat peraga secara internal dan membiarkan pengguna untuk secara eksplisit menentukan apakah dua sumber data terpisah (yaitu alat peraga saat ini dan berikutnya) harus menyebabkan pembaruan atau hanya menjadi diabaikan.

Akan lebih baik untuk melihat lebih banyak diskusi seputar detail spesifik ini jika orang-orang merasa yakin bahwa hal itu harus dilaksanakan.

Adapun implementasi sederhana dari ini jika kita memang ingin melanjutkan dengan ini, saya kira Anda akan terus menggabungkan childContextTypes komponen saat Anda memperbarui pohon untuk membandingkan dengan contextTypes untuk menemukan yang valid perbarui target. Atau mungkin kita bisa melakukan sedikit keajaiban di mount dan membuat hubungan orang tua / anak hanya antara anak dan orang tua terdekat dengan kunci anak konteks yang cocok. Saya merasa yang terakhir akan membuat sulit untuk mengelola urutan pembaruan nanti meskipun jika bukan tidak mungkin.

Saya akan melakukan retasan cepat dan mencoba mengejek ini sekarang!

Sebenarnya mengenai saran terakhir saya untuk bagian perbandingan kunci konteks spesifik dari fungsionalitas, mungkin tidak sesulit mempertahankan urutan pembaruan jika kita hanya mengikuti logika batch urutan yang sama yang sudah digunakan!

@Chrisui @sebmarkbage Jadi perhatian saya (kecuali saya lupa / melewatkan sesuatu yang jelas) adalah bahwa setiap kali penyedia konteks merender ulang, itu akan menyebabkan semua (berpotensi ratusan) komponen anak yang bergantung pada variabel konteks yang disediakan untuk render ulang, meskipun variabel konteks tidak berubah. Intuisi saya adalah kita seharusnya hanya memicu propagasi ulang konteks jika kita memiliki semacam indikasi bahwa nilai baru tersedia (seperti nilai baru yang tidak tiga kali lipat sama dengan nilai lama, atau beberapa bendera / pemberitahuan).

Sebenarnya implementasi ini mulai terlihat seperti sistem berlangganan. Karena context secara efektif merupakan cakupan global, mungkin solusi yang tepat adalah meminta komponen untuk berlangganan ke variabel konteks, sehingga memungkinkan kita untuk menggunakan mekanisme yang sama untuk konteks yang akan kita gunakan untuk semua langganan lain ke global data. Lihat https://github.com/facebook/react/issues/3398 , https://github.com/facebook/react/issues/3858 , dan https://github.com/facebook/react/pull/3920 untuk informasi yang relevan.

Menyodok @sebmarkbage. Saya pikir pemikiran terbaru saya mendukung penggunaan solusi pemuatan data samping kami untuk memecahkan masalah ini, untuk menghindari area permukaan API. Saya penasaran untuk mendengar pemikiran Anda.

@jimfb Anda benar tentang memiliki ratusan komponen yang dirender ulang tetapi saya tidak yakin itu berbeda dengan sekarang jika Anda memicu beberapa perubahan status dan harus menerapkan shouldComponentUpdate untuk mencegah pembaruan massal terjadi.

Saya setuju meskipun konteks itu hanya terlihat seperti aliran data sampingan tertentu. Jika proposal tersebut dapat memiliki efek berjenjang dari konteks, saya tidak melihat alasan untuk benar-benar mengembangkan konteks seperti sekarang. Mari kita lihat apa yang dipikirkan orang lain!

Karena tertarik, saya menambahkan fungsionalitas ke draf saya untuk hanya membuat hubungan induk / anak antar komponen jika mereka memiliki kunci konteks / anak yang cocok (mencegah penjelajahan pohon yang berlebihan) dan mencegah pembaruan jika konteks tidak benar-benar berubah hanya akan dilakukan dengan PureRenderMixin seperti biasa.

@Chrisui Saya pikir perbedaannya adalah bahwa shouldComponentUpdate tunggal dalam komponen anak dapat memotong cabang besar pohon, sedangkan dengan konteks, jauh lebih sulit untuk menemukan / memperbaiki semua tempat yang akan dirender ulang. Bahkan jika Anda ditalangi, anak yang bergantung pada variabel konteks akan tetap dirender ulang.

Ya, saya ingin tahu apa yang dipikirkan orang lain tentang penggunaan solusi pemuatan data samping.

Saya pikir konteks sebagian besar ortogonal dengan pemuatan data ke samping

Idealnya saya ingin cara untuk memberikan pegangan untuk penyimpanan data samping saya ke komponen yang bukan global - ini sebagian besar adalah bagaimana saya menggunakan konteks.

Menggunakan konteks untuk DI seperti ini mengurangi kemungkinan itu akan berubah selama aplikasi berlangsung.

Pada 26 Mei 2015, pukul 22:10, Jim [email protected] menulis:

@Chrisui Saya pikir perbedaannya adalah bahwa shouldComponentUpdate tunggal dalam komponen anak dapat memotong cabang besar pohon, sedangkan dengan konteks, jauh lebih sulit untuk menemukan / memperbaiki semua tempat yang akan dirender ulang. Bahkan jika Anda ditalangi, anak yang bergantung pada variabel konteks akan tetap dirender ulang.

Ya, saya ingin tahu apa yang dipikirkan orang lain tentang penggunaan solusi pemuatan data samping.

-
Balas email ini secara langsung atau lihat di GitHub.

Sepertinya semua saran saat ini seputar penggunaan konteks (di luar "jangan") masih akan berlaku, di mana apa pun yang sering berubah akan menimbulkan biaya render ulang yang cukup tinggi. Meningkatkan biaya tersebut dengan cara yang sangat tepat sasaran tidak serta merta mengubah cara orang berpikir tentang penggunaannya. Plus, jika Anda ingin memotong cabang pohon, itu masih cukup mudah:

class Mid extends Component {
  shouldComponentUpdate() { return false; }
  shouldUpdateChildContext() { return false; }
  ...
}

Saya senang dengan kesederhanaan relatif dari konteksnya + shouldUpdateChildContext. Mudah-mudahan mengubah mekanisme yang mendasari agar sejalan dengan langganan global lainnya tidak akan mengurangi kemudahan penggunaannya secara dramatis.

@tokopedia
Sebagai @eplawless telah menunjukkan shouldUpdateChildContext dapat digunakan untuk memblokir cabang besar pohon Anda sedang diperbarui.

Saya pikir api konteks (dengan perubahan yang diusulkan) cukup sederhana sehingga kita dapat menerapkan sekarang dan mengubah internal untuk menggunakan data sisi pemuatan yang mungkin didukung reaksi nanti.

Saran lain: Kita juga bisa membuat shouldUpdateChildContext () default ke false untuk mencegah perilaku baru ini secara default dan membuatnya ikut serta.

Demi iterasi dan mendapatkan sesuatu ke alam liar untuk diuji (dengan cara yang sama fitur konteks selalu - karenanya tidak terdokumentasi) haruskah kita mengejar proposal api ini untuk 0,14? (Akan menyenangkan mendengar dari penjaga gerbang!)

Saya membuka PR untuk Anda: https://github.com/facebook/react/pull/3973

Kemungkinan besar Anda akan mendapatkan umpan balik yang cepat tentang PR karena mereka lebih mudah ditinjau dibandingkan dengan master dan mendapat prioritas atas masalah.

Anda tahu saya pikir awalnya saya salah tentang shouldUpdateChildContext . Apakah kita benar-benar membutuhkannya? Maaf tentang thrash.

Sepertinya shouldComponentUpdate adalah strategi yang menjadikan tanggung jawab seorang anak untuk menentukan apakah sesuatu telah berubah. Misalnya, mungkin tidak menggunakan semua data yang Anda berikan untuk menentukan keluarannya. Sebagai orang tua, Anda tidak tahu itu. Mungkin itu sudah cukup.

Saya juga berpikir bahwa kita mungkin ingin membatasi koneksi induk-> anak ke satu set properti tetap, seperti props. Yaitu Anda tidak akan dapat memiliki beberapa konteks berbeda yang disediakan dari satu sumber, di mana setiap anak tertentu hanya menggunakan bagian dari konteks tersebut. Mungkin ada pemetaan 1: 1. Selain itu, saya selalu ragu untuk memiliki gelembung konteks langsung melalui anak yang mengonsumsinya, sementara kasus penggunaan yang sah umumnya adalah "lubang cacing" antara dua komponen, bukan hanya menyiarkan ke semua orang (yang merupakan anti-pola).

Saya akan memikirkannya lagi dan mengomentari PR dengan detail ...

@sebmarkbage Saya bisa memilih shouldUpdateChildContext . Preferensi saya selalu meminimalkan permukaan API. Kita selalu bisa membiarkannya keluar dari API awal (konteks hanya melompat melalui dan memulai render ulang pada komponen apa pun yang membaca variabel konteks). Jika orang membutuhkan pintu keluar tambahan, kami menambahkannya nanti.

Saya pikir masalah yang lebih besar, seperti yang ditunjukkan @mjackson , adalah kita tidak tahu kapan variabel konteks berubah. Apakah kita benar-benar ingin merender ulang setiap simpul teks fbt / i18n setiap kali ContextProvider i18n merender ulang? Kami belum memberikan cara untuk mengatakan "jangan khawatir, tidak ada yang berubah, jangan repot-repot merender ulang setiap elemen teks di halaman".

Saya sedikit bingung tentang paragraf terakhir Anda; bisakah kamu menjelaskannya? Saya berasumsi Anda tidak menyarankan bahwa berikut ini adalah anti-pola konteks: Komponen i18n 'menyiarkan' ke semua komponen anak yang sadar-i18n, bahasa / zona waktu / pemformatan / dll. Yang disukai pengguna.

Berkomentar di PR, sebaiknya perbanyak disini saya kira:

@sebmarkbage @Chrisui @jimfb

Re: shouldUpdateChildContext , saya rasa ini adalah tambahan yang berguna. Secara default shouldComponentUpdate mengembalikan nilai true, yang menjadikannya tanggung jawab anak untuk menentukan apakah sesuatu telah berubah. Menerapkan shouldComponentUpdate berarti Anda mengambil tanggung jawab itu jika orang tua lebih tahu. Hal yang sama berlaku untuk shouldUpdateChildContext , itu hanya ada untuk menghilangkan tanggung jawab dari anak-anaknya sebagai optimasi.

Re: tidak menyiarkan ke seluruh subpohon, saya pikir ada dua pola yang valid. Lubang cacing, seperti yang Anda sarankan di # 2517, sangat masuk akal. Kami menggunakan pola itu untuk mengelompokkan item dalam berbagai subsistem (seperti fokus dan suara). Selain itu, kami ingin menggunakan konteks untuk meneruskan informasi i18n ke seluruh bagian (mungkin keseluruhan) aplikasi kami, dan memaksa rendering ulang apa pun yang menggunakannya. Pola siaran seperti itu mungkin relatif jarang dibandingkan dengan pola lubang cacing, tapi saya yakin itu masih berlaku.

Saat ini kami terkadang menggunakan mixin untuk fokus dan grup suara dari sumber yang sama. Saya pikir ada kasus penggunaan yang valid untuk tidak memaksakan pemetaan 1: 1, meskipun saya memahami keinginan untuk pembatasan tersebut.

Saya sebenarnya mengira pola "lubang cacing" adalah antipattern, dan siaran adalah pola yang diharapkan. Konteks hanya menarik jika ada banyak konsumen variabel (mis. Jika melewatkan prop secara eksplisit akan mengakibatkannya ditambahkan ke hampir setiap komponen dan oleh karena itu banyak boilerplate), jika tidak, mungkin lebih baik untuk menyebarkannya secara eksplisit sebagai a menopang. Tetapi @sebmarkbage tampaknya mengatakan sebaliknya (dan dia biasanya benar tentang hal ini), jadi sekarang saya bingung dan ingin mendapatkan klarifikasi darinya.

@sebmarkbage @eplawless Apa contoh pola wormhole yang menurut Anda valid? Apa yang orang tua berikan, bagaimana itu digunakan oleh anak, mengapa tidak bisa hanya menjadi penyangga pada anak, dll.

<Table>
  <Cell />
  <Cell />
  <FancyCell />
</Table>
class FancyCell {
  render() {
    return <SomeWhatFancyCell>Some content</SomeWhatFancyCell>;
  }
}

class SomeWhatFancyCell {
  render() {
    return <Cell>{this.props.children}</Cell>;
  }
}

Ambil borderWidth dan berikan ke semua sel tabel dalam bentuk borderLeft/Top/Right/Bottom .

Salah satu cara yang rapi adalah dengan mengirimkan borderWidth ke <Table /> , membaginya dan melewati konteks.

Ini menyediakan cara untuk sesuatu yang mungkin dirender ke Sel untuk berkomunikasi dengan induk konseptualnya seperti Tabel melalui saluran tersembunyi. Ini sudah dilakukan elemen DOM satu sama lain dan kemungkinan besar diperlukan untuk melakukan tata letak di React.

Jangan terlalu fokus pada konsep "konteks". Konsep saat ini tidak ideal. Mungkin yang ideal adalah seperti dua konsep berbeda atau saluran lain?

API alternatif yang masuk akal:

class Table {
  render() {
    var w = this.props.borderWidth;
    var borderStyle = { left: w, right: w, top: w, bottom: w };
    return <context key={someSymbol} value={borderStyle}>{this.props.children}</context>
  }
}
class Cell {
  static contextKey = someSymbol;
  render() {
    var borderStyle = this.context;
    ...
  }
}

Hanya meludah disini.

Melanjutkan spitballing ...

Bisa menggunakan sintaks alternatif ...

<Table borderStyleChannelKey="myKey">
  <Cell borderStyle={myKey} />
  <Cell borderStyle={myKey} />
  <FancyCell borderStyle={myKey} />
</Table>

Sekarang Anda telah membuat saluran komunikasi eksplisit, menghindari semua kemungkinan konflik nama, dan lain-lain (https://github.com/reactjs/react-future/pull/28)

Simbol juga tidak memiliki konflik nama, tetapi Anda telah membuat saluran komunikasi dengan biaya. Anda telah melewatinya melalui berbagai tingkat tipuan. Kapan pun Anda perlu mengubah atau menambahkan saluran lain, seperti warna latar belakang, Anda perlu memperbarui semuanya meskipun kontrak yang didokumentasikan (Sel di dalam tabel) masih sama.

Btw, inti dari React sudah IS saluran komunikasi tersembunyi: negara. Itu tidak secara eksplisit melewati setiap anak.

Sebut saja 'styleinfo' atau 'celldata' alih-alih 'borderStyle', dan jadikan sebagai objek. Kemudian menambahkan bidang / info tidak perlu mengubah kontrak API antara Table dan Cell .

Satu-satunya perbedaan antara varian saya dan varian Anda adalah bahwa (dalam varian saya) satu-satunya cara bagi anak untuk benar-benar "membaca" nilainya adalah dengan membuatnya diteruskan secara eksplisit sebagai prop dari induknya. Secara fungsional, proposal terbaru Anda benar-benar identik dengan proposal saya dari https://github.com/reactjs/react-future/pull/28.

Untuk lebih jelasnya, saya sangat menyukai proposal terbaru Anda ... jadi saya tidak akan mengeluh ... tetapi ini menyelesaikan masalah yang sedikit berbeda. Itulah yang Anda katakan kepada saya di bulan Maret, dan saya akhirnya sampai pada kesimpulan bahwa Anda benar (misalnya, masalah siaran). Jika kita baik-baik saja dengan tidak menyelesaikan masalah siaran (yaitu bagaimana saya yakin bahwa konteks memang memberikan nilai), maka tentu saja, mari kita lakukan sesuatu seperti ini!

Simbol sewenang-wenang memang memiliki konflik nama, kecuali nama kunci selalu diputuskan oleh pemiliknya, dalam hal ini Anda mungkin juga membuatnya terlihat oleh pemilik karena pemilik tetap perlu mengomunikasikan nama kunci kepada anak (jika tidak, bagaimana anak tahu ke mana harus mencari?). Dengan memaksa pemilik untuk terlibat, Anda secara alami mendorong komponen untuk menggunakan simbol daripada kunci kode keras.

Maksud saya Simbol global (kapital S) yang harus diatur melalui beberapa saluran seperti modul umum. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

Bagian yang menyenangkan tentang API baru saya yang diusulkan adalah bahwa kuncinya bukanlah kunci "properti objek" yang menjadi bingung dengan aliran kontrol dan analisis program. Dalam proposal saya adalah nilai dinamis kelas satu seperti kunci yang menggerakkan negara.

Oh, ya, @sebmarkbage mengeluarkan javascript baru yang keren lagi :). Saya seharusnya telah mengetahui; dia ada di pertemuan TC39 hari ini.

Oke, kamu benar. Itu akan sangat efektif dalam menghindari konflik nama, dan akan menyelesaikan masalah siaran. Anda telah menjual saya. Saya suka itu!

Saya berharap Anda ada di kantor hari ini! Saya merasa ini akan menjadi percakapan yang sangat menarik untuk dilakukan secara langsung!

Secara pribadi saya senang dia tidak melakukannya, karena ini membuat kita semua tetap terhubung juga ;-).

Saya sangat menyukai hal Symbol. Konteks yang terlalu bergantung pada kunci string di pohon yang berpotensi asing selalu memiliki getaran yang buruk.

Misalnya, jika dua pustaka bergantung pada lubang cacing induk-anak di pustaka ketiga, dan kebetulan menggunakan salinan independennya, salinan tersebut tidak akan bentrok atau saling melihat. Tentu ini skenario yang aneh untuk dibayangkan, tetapi tampaknya lebih konsisten.

Agar adil, Simbol sudah dimungkinkan untuk bekerja pada objek saat ini. Bahkan jika Anda menggunakan Simbol, Anda mungkin akan membutuhkan modul melalui namespace yang berpotensi global seperti nama modul tingkat atas npm (meskipun mudah-mudahan itu relatif).

Hanya saja API saat ini membuatnya sangat alami untuk menggunakan nama string sederhana. Ini juga menggabungkan semantik runtime dengan pengenal properti tertentu, membuat hal-hal seperti mode lanjutan compiler closure lebih sulit untuk dipikirkan. Sekrup juga dengan pengoptimalan VM.

@sebmarkbage Anda dapat menggunakan UUID (alias Simbol), ya, tetapi proposal baru Anda memungkinkan kunci untuk diputuskan pada waktu proses, yang berarti induk BISA mempengaruhinya melalui alat peraga (meskipun tidak yakin apa yang Anda pikirkan). Karena itu, saya tidak yakin seberapa berguna itu tanpa membuat nilai tersedia dalam lingkup jsx, saya perlu memikirkannya lebih banyak, tetapi itu menambahkan beberapa fleksibilitas yang keren (mungkin).

Saya tidak begitu yakin tentang analogi "lubang cacing", skenario siaran dan contoh i18n adalah orang-orang di mana saya mengalami masalah yang ingin diselesaikan oleh PR yang diusulkan.

Saya juga tidak sepenuhnya mengerti bagaimana https://github.com/facebook/react/issues/2517#issuecomment -106597895 membantu - ini tampaknya secara semantik setara dengan getChildContext dan contextTypes bagi saya.

Apa yang saya suka tentang shouldUpdateChildContext PR adalah bahwa ia tidak memerlukan pencacahan semua anak pada kedalaman apa pun untuk menyebarkan perubahan konteks.

AIUI Masalah aslinya selalu adalah meskipun shouldComponentUpdate dilewatkan context , sifat konteksnya berarti bahwa komponen di antara "penyiar" dan "penerima" bisa kembali salah karena tidak tahu konteksnya sedang melewatinya.

Sepertinya dua cara untuk mengatasi masalah ini adalah dengan melacak komponen mana yang membaca dari konteks di atasnya pada pohon, atau memiliki mekanisme tambahan untuk menyebarkan perubahan konteks ke bawah pohon.

Saya ingin menawarkan 2 sen saya pada subjek setelah menggunakan konteks berbasis orang tua di komponen formulir kami sebentar. Kurangnya mekanisme pembaruan yang baik antara orang tua dan anak-anak tergantung pada konteks yang menyebabkan pembuatan paralel, mekanisme seperti fluks di mana formulir (berfungsi sebagai instance 'store') meneruskan metode listen() melalui konteks, ke mana Field Komponen mendaftar di mount. Formulir tersebut akan memicu perubahan yang merambat ke bawah. Semuanya sangat fluks-y dan berfungsi dengan baik tetapi itu menghancurkan model komposabilitas dari Komponen React.

Strategi umum untuk membungkus komponen dalam HoC tidak berfungsi di sini karena ia menempatkan komponen baru, membungkus, _outside_ saluran pembaruan, bukan di tengahnya (seperti pada props). Manfaat besar untuk sistem penyangga adalah alirannya dari atas ke bawah dan dapat dicegat oleh apa pun yang terjebak di antaranya. Dalam kasus di sini menggunakan fluks seperti sistem pembaruan, komponen pembungkus juga perlu mendengarkan Formulir, tetapi kemudian Anda mengalami masalah di mana komponen pembungkus dan komponen asli (pembungkus) mendengarkan Formulir, sebagai gantinya dari HoC "mengambil alih" dan meneruskan data ke komponen aslinya.

Konteks jelas perlu "dilindungi" agak dari komponen yang tidak memiliki urusan dengan konteks tertentu _but_ itu perlu sederhana untuk melompat ke aliran data jika komponen menginginkannya. Dalam kasus khusus komponen formulir kita, kebanyakan turunan dari Form harus diisolasi dari konteks yang diteruskannya, dan hanya komponen Field akan menerimanya. Namun, jika konsumen ingin membungkus Field dalam HoC (untuk menyetel default atau menyesuaikan perilaku) harus ada beberapa cara mudah untuk melakukannya.

yang berarti bahwa API konteks apa pun benar-benar harus mengizinkan komponen perantara (resmi) untuk bertindak sebagai pereduksi untuk konteks tersebut, dengan cara yang sama komponen dapat mengurangi / memetakan alat peraga saat mereka meneruskannya ke anak-anak. perbedaannya adalah bahwa sementara props adalah steam "publik", konteksnya adalah private, opt in, stream

Saya telah bermain-main sedikit dengan gagasan konteks berbasis langganan di atas konteks sisi-reaksi .

Di bawah tenda, penyiar konteks mengekspos antarmuka { subscribe(key, cb), getValue(key) } kepada anak-anak mereka. Langganan ke kunci konteks menggembung pohon konteks hingga mencapai penyiar dari kunci tertentu atau puncak pohon. Penyiar mengirimkan perubahan ke kunci konteks melalui broadcast({ [key]: newValue, ...otherKeys }) .

@broadcasts([...keys]) dan @observes([...keys]) class dekorator mengikat API ini ke komponen React, menggunakan context untuk menyebarkan pohon konteks melalui pohon komponen dan setState untuk mengantrekan pembaruan di menanggapi perubahan konteks.

Dengan sedikit boilerplate , Anda dapat menyiapkan API yang setara dengan proposal shouldUpdateChildContext .

Untuk menghindari benturan nama, struktur pohon konteks bersifat unik , jadi Anda memerlukan referensi ke konteks untuk menyiarkan atau mengamati kunci di dalamnya.

Saya tidak pernah menggunakan konteks untuk meneruskan nilai dinamis apa pun, hanya referensi yang tidak berubah. Saya melihat beberapa contoh mainan itu di sini, tetapi adakah yang menggunakannya untuk menyampaikan nilai dinamis dalam aplikasi produksi? Saya sering menemukan kasus penggunaan dunia nyata yang lebih mencerahkan.

Misalnya untuk I18n, apakah ada yang meneruskan pasangan nilai kunci secara langsung? Atau apakah Anda hanya meneruskan referensi yang tidak berubah ke komponen objek yang bisa mendapatkan nilai dari dan mengamati?

Saya tertarik pada suatu waktu untuk menerapkan semacam acara gelembung-up yang dikirim dalam konteks, saya lupa untuk apa sebenarnya, tetapi idenya adalah memungkinkan orang tua untuk mencegat dan menambahkan lebih banyak konteks ke acara yang datang dari anak-anak sehingga anak-anak tidak akan memilikinya untuk mengetahui posisi mereka dalam konteks global.

Untuk menambahkan 2 sen saya di sini, saya akan sangat memilih jika ada perbaikan di sini yang diterapkan sedemikian rupa sehingga tidak merusak StaticContainer .

Saya pikir akan lebih masuk akal StaticContainer terus bekerja seperti itu, dan memblokir semua pembaruan yang datang dari orang tua, baik props dan context .

IMO cara terbaik untuk menangani ini adalah dengan mengizinkan shouldComponentUpdate untuk secara potensial mendeteksi perubahan konteks yang digunakan oleh anak-anak, daripada mengabaikan shouldComponentUpdate sepenuhnya setiap kali konteks terlibat.

@ jedwards1211 Kasus penggunaan saya adalah mengambil pesan terjemahan di dalam komponen I18nProvider dan kemudian meneruskan contoh Jed (dengan metode gettext).

Sebelum pesan diterima, metode gettext akan mengembalikan string kosong, agar UI dapat dirender secara optimal. Ketika I18nProvider telah menerima pesan, saya berharap semuanya akan dirender ulang, dengan hanya bagian dengan string yang dapat diterjemahkan yang diperbarui di DOM.

Saya harus benar-benar memiliki panggilan gettext() dalam komponen tampilan sehingga saya dapat mengekstrak string (menggunakan xgettext dalam kasus ini).

Menendang ini sekitar dengan @jquense sedikit di Reactiflux; akan berguna jika ada konsep "super false " untuk shouldComponentUpdate .

Meskipun secara umum tampaknya pembaruan konteks harus menyebar melewati shouldComponentUpdate mengembalikan false (atau setidaknya ini akan membuat sebagian besar kasus penggunaan lebih sederhana), saya juga berpikir ada kasus khusus dengan misalnya <StaticContainer> yang mengharuskan induk untuk dapat memblokir semua pembaruan ke turunannya, untuk tujuan seperti membekukan subpohon yang sedang bertransisi keluar, seperti <StaticContainer> .

Misalnya, pertimbangkan https://github.com/rackt/react-router/pull/2454 - tanpa kemampuan untuk memblokir pembaruan konteks untuk anak-anak, kami tidak akan dapat dengan mudah mencegah pembaruan untuk menautkan status aktif pada transisi- komponen rute keluar.

Saya setuju bahwa perilaku untuk shouldComponentUpdate mengembalikan false seharusnya tidak memblokir pembaruan konteks, tetapi harus ada semacam SUPER_FALSE sentinel untuk menyimpan <StaticContainer> bekerja apa adanya.

@taion

tidak akan dengan mudah dapat mencegah pembaruan untuk menghubungkan status aktif pada komponen rute transisi keluar.

Saya bingung, use case apa yang diinginkan? Secara umum, shouldComponentUpdate TIDAK boleh digunakan untuk memblokir pembaruan yang akan mengakibatkan perubahan UI. Ini adalah petunjuk yang dimaksudkan semata-mata sebagai mekanisme pengoptimalan untuk memungkinkan Anda menghindari melakukan pekerjaan rekonsiliasi yang tidak perlu.

@jimfb Anda sudah menggunakan <StaticContainer> untuk melakukan persis seperti itu di Relay - yaitu untuk memblokir pembaruan saat memuat data baru.

Saya pikir kasus penggunaan di sana adalah bahwa pengguna mengklik tautan, memicu rute baru untuk dimuat / ditukar. Saat ini terjadi, idenya adalah memblokir semua interaksi / pembaruan pada rute lama, yang akan ditukar ketika yang baru selesai memuat.

Kedengarannya seperti saat ini dilakukan dengan selalu mengembalikan false dalam shouldComponentUpdate saat status router baru sedang dimuat.

@taion Saya akan berbicara dengan orang-orang Relay dan mencari tahu apa yang terjadi di sana. Sampai kami memiliki jawaban yang pasti tentang itu, saya tidak akan merekomendasikan menerapkan teknik itu dalam kode Anda sendiri.

cc @eblog

@tokopedia

Mungkin lebih mudah bagi Anda untuk melakukannya (:

Pemahaman saya tentang idenya adalah, ketika memicu data baru untuk dimuat, secara default kami ingin terus merender data lama hingga data baru siap.

Dengan mengembalikan false dari shouldComponentUpdate , Relay root container / renderer memiliki cara mudah untuk menyimpan rendering apa pun yang ada sebelumnya.

Itu tidak memblokir interaksi itu sendiri - itu memblokir data upstream yang mengambil pembaruan saat berada dalam status sementara.

@taion Ya, saya mengerti apa yang dilakukannya, tapi saya skeptis bahwa itu adalah pola yang ingin kami dukung. Saya akan berbicara dengan Sebastian dan orang-orang estafet, tetapi tebakan saya adalah jawabannya adalah "ya, itu hack, jangan lakukan itu".

Biasanya, cara Anda mencapai perilaku itu, adalah memasukkan nilai lama ke status (sampai nilai baru muncul / tiba) dan membuat nilai lama dari status.

@tokopedia

Pola itu hanya mungkin dengan data yang tidak dapat diubah atau sesuatu yang serupa. Jika Anda memiliki objek stateful (non-clonable), Anda mungkin tidak dapat mengikuti pola ini. Saya menduga Relay mungkin tidak mengalami masalah ini, tetapi implementasi React Router saat ini memang memiliki masalah ini.

Untuk pustaka data asinkron umum, ini tampak seperti pola yang cukup umum dan nyaman.

@taion Pendekatan yang Anda pertimbangkan tampaknya lebih rentan terhadap kesalahan bagi saya TERUTAMA dalam kasus di mana Anda memiliki data yang bisa berubah. Jika data Anda dapat berubah, maka Anda akan memiliki kondisi balapan di mana terkadang anak-anak memperbarui secara acak (karena pengendali peristiwa, perubahan konteks, pembaruan paksa, dll), dan kode Anda menjadi sangat tidak dapat diprediksi. Biarkan saya menyelaraskan dengan beberapa orang dan mencari tahu ini. Ping saya dalam beberapa hari jika saya belum memposting hasil diskusi itu.

Saya tidak berpikir kasus penggunaan StaticContainer adalah sesuatu yang harus ditangani melalui pola itu. Kedengarannya seperti cara yang tidak stabil untuk mencoba dan mendapatkan efek dari efek samping fitur lain. Akan jauh lebih baik jika memiliki dukungan eksplisit untuk apa yang sebenarnya diminta.

Dalam hal ini, tampaknya permintaannya adalah beberapa pustaka React level rendah menginginkan cara untuk mencegat unmount, menceraikan DOM yang dihasilkan dari sebuah komponen dari pohon React, memutus koneksi dan menunda siklus hidup unmount hingga selesai.

Saya rasa ini adalah fitur tingkat rendah yang harus kami dukung dengan antarmuka eksplisit. Beberapa cara untuk melepaskan atau mencegat pelepasan komponen, yang memutus tautan, memungkinkan pemanggil untuk mengacaukan konteks yang mendasarinya untuk sementara, dan mengembalikan fungsi yang akan melanjutkan aliran siklus hidup pelepasan saat dipanggil.

Kita mungkin memerlukan beberapa bentuk fragmen atau placeholder khusus yang dapat digunakan API ini untuk memberi tahu React secara eksplisit bahwa simpul DOM yang terputus dari React harus disimpan di lokasi tertentu.

Itu tidak bisa dilakukan tanpa node internal super khusus. Tetapi sekali lagi gagasan tentang tipe node react level rendah khusus yang dirender sebagai noscript (tipikal react hack untuk pengembalian nol, dll ...) dan menyatakan bahwa nextSiblingnya adalah node DOM yang harus disimpan di lokasi itu tetapi jika diabaikan oleh React akan menjadi tipe node yang sangat menarik yang dapat berguna dalam memperbaiki berbagai bug lainnya.

@taion Ok, saya baru saja berbicara dengan satu orang di tim Relay, dan beberapa orang React lainnya. Kami semua sepakat bahwa ini bukanlah pola yang baik. Tolong jangan lakukan itu. Menggunakan negara untuk menyimpan data Anda sambil menunggu pembaruan adalah solusi resmi, sampai kami menemukan api / rekomendasi yang lebih baik untuk kasus penggunaan itu.

Saya dapat mengatasinya - saya pikir kami telah membersihkan beberapa hal di sisi React Router sehingga kami dapat beralih dari menggunakan pola ini.

Terima kasih!

Saya juga ingin menambahkan satu pertanyaan lagi. Saya punya sesuatu seperti ini.

var BlogPosts = React.createClass({
  getChildContext: function() {
    return {
      currentBlogPost: this.props.currentBlogPost,
      currentUser: this.props.currentUser
    };
  },

  childContextTypes: {
    currentBlogPost: React.PropTypes.object,
    currentUser: React.PropTypes.object
  },

  render: function() {
    return <BlogPosts blogPosts={this.props.blogPosts}/>
  }
});

function select(state) {
  const { blogPosts, currentUser, currentBlogId } = state;
  console.log( state.blogs[currentBlogId]); 
  // first time the above is undefined and then blogs get populated and I have the object;
  return { blogPosts, currentUser, currentBlogPost: state.blogs[currentBlogId] };
};

export default connect(select)(BlogPosts);

sekarang di komponen BlogPosts ada BlogPostText, BlogPostImage, PodCast ... tergantung dari apakah blogPosts [index] .type adalah teks, gambar, atau audio.

di salah satu komponen sudah saya periksa pemiliknya seperti ini,

var BlogPostText = React.createClass({
  canDeleteMemory: function(post, blog, user) {
    return user && (blog.userId == user.id || post.userId == user.id)
  },
  render: function() {
    let isOwner = this.canDeleteMemory(this.context.currentBlogPost, post, this.context.currentUser);
    return isOwner ? <a>Delete</a> : null;
  }
});

kemudian saya selalu mendapatkan error di blog.userId karena blog tidak terdefinisi ... jadi saya ubah kondisi seperti ini let isOwner = this.context.currentBlogPost && this.canDeleteMemory(this.context.currentBlogPost, post, this.context.currentUser);
tetapi kemudian ikon hapus tidak pernah muncul ... tetapi daripada menggunakan contextType jika saya membungkus komponen BlogPostText dengan redux pilih dan gunakan this.props.currentBlogPost maka berfungsi dengan baik ..

jadi perubahan konteks tidak memicu render ulang atau sesuatu seperti itu ... atau saya salah menggunakannya.

@ aghosh47 Saya pikir perubahan konteks memang memicu rerender, tetapi mungkin saja kami melewatkan kasus edge. Jika Anda dapat membuat jsfiddle sederhana yang menunjukkan masalah tersebut, itu akan membantu kami menyelidiki.

Juga, silakan posting ke masalah baru, karena kami ingin menjaga topik masalah github, sejauh mungkin.

@jimfb ok, saya akan memeriksa kembali kode saya, melihat apakah saya melewatkan sesuatu dan membuat utas baru jika saya tidak dapat menyelesaikannya .. Saya baru saja mulai dengan bereaksi .. dan sebenarnya sulit untuk menemukan bantuan yang berkualitas. jadi, terima kasih atas umpan baliknya .. menghargai itu.

@jimfb dimana pembahasan tentang reparenting tanpa remount turunan? Saya tidak akan pernah mengharapkan hal seperti itu, jadi saya khawatir bahwa perubahan perilaku yang tidak terduga dapat mengakibatkan aplikasi saya dengan versi React yang akan datang jika itu diperkenalkan. Jadi saya ingin tetap mendapat informasi tentang diskusi itu

Kasus penggunaan lain untuk konteks yang saya temukan adalah ketika sebuah komponen berada di bawah beberapa grup transisi. Misalnya, saya ingin dapat memfokuskan input ketika semua grup transisi leluhurnya benar-benar muncul / masuk, daripada awalnya dipasang. Mendaftarkan callback untuk leluhur yang muncul / masuk melalui metode yang diturunkan melalui konteks akan menjadi cara yang paling nyaman untuk melakukannya.

@ jedwards1211 Sejujurnya, saya tidak ingat di mana hal itu dibahas. Sangat mungkin bahwa itu adalah diskusi langsung, tetapi ada banyak diskusi reparenting online dan mungkin Anda akan menemukannya di sana.

Ping @ agosh47

Ha ha ha

@jimfb baiklah, masalah telah teratasi ... ada beberapa kesalahan dalam kode dan orang yang menulis kode tidak menggunakan tangkapan untuk menyelesaikan kesalahan apa pun dari janji, jadi status peredam tidak diperbarui dengan benar dan karenanya perubahannya tidak tidak dipantulkan.

Jadi, jika props di dalam induk berubah, contextType pada anak-anak akan direfleksikan ... Terima kasih.

apa yang salah dalam menggunakan window untuk satu objek yang menyimpan global tersebut?

@cauburtin Ini tidak benar-benar berfungsi di sisi server tempat semua komponen yang dibuat berbagi status global yang sama. Konteksnya global, semua komponen yang dirender dalam satu pohon, tetapi lokal ke pohon itu sendiri. Itu tidak bocor ke pohon lain, tidak seperti keadaan global.

Di samping catatan, pertanyaan ini tidak ada hubungannya dengan masalah tersebut, bukan? :mengedipkan:

@fatfisz Saya tidak tahu betul kasus penggunaan Anda, Anda juga dapat memiliki require ('foo') yang mengarah ke properti jendela hanya pada klien

btw di aplikasi saya, saya akhirnya meneruskan objek di props dari semua komponen, karena konteksnya tampak tidak jelas, dan karena hampir semua komponen menggunakannya dalam kasus saya

Terima kasih

apa yang salah lakukan:

// context.js
module.exports  = { // sorry for using commonjs, since most of you use import/export I guess
  // some shared variables, initialized and used by components
};

kemudian membutuhkan ('./ context.js'); di semua file yang perlu mengakses variabel konteks dan metode

enkapsulasi mungkin tidak dihormati, tapi yah ..

(@rumahsakit)

@cauburtin Konteks berguna karena:

1) Dapat mengubah dan memicu rendering ulang tidak seperti ekspor modul
2) Dapat diganti oleh induk, yang merupakan fiturnya yang paling berguna
3) Tidak harus tunggal, yang berguna untuk rendering server di mana Anda ingin mengisolasi data

Setuju untuk 2) dan 3)
Untuk 1) Saya belum perlu melakukan itu, tetapi Anda dapat memberikan contoh react dalam konteks juga (Saya sering mendengar bahwa ini adalah praktik yang buruk, Anda mungkin juga berpikir demikian, tetapi bahkan disebutkan dalam dokumen: Ingat itu Anda juga bisa meneruskan seluruh komponen React dalam props jika Anda mau (di mana props bisa menjadi konteks tunggal ini sebagai gantinya dalam kasus ini). Bagi saya, React adalah view, event listener dan remote control (top / root). Dan konteks bersama ini akan menjadi akses bersama ke kendali jarak jauh. Sub komponen dapat memperbarui ketika alat peraga mereka berubah, dan mungkin akses ke dan menggunakan konteks global itu. (Bukan penggemar lajang dalam kasus ini khususnya, saya dapat menggunakan kembali 'passing down react instance dengan cara props, jika itu berguna, 'passing down' ini bisa lebih atau kurang diotomatiskan / disembunyikan oleh kelas atau komposisi induk yang sama)

Nah menulis ini, saya menyadari bahwa gagasan konteks tunggal itu buruk :)

Yang membingungkan adalah bahwa dokumen React tidak mengundang banyak untuk menggunakan konteks, mereka sebenarnya seperti alat peraga opsional, di mana Anda mendapatkannya ketika Anda memintanya?

Saya mengimplementasikan Drawer di android menggunakan react native dan mencoba membuat file yang berbeda untuk kode menu laci dan kode konten laci. Untuk melakukan ini saya telah membuat komponen react dengan cara yang berbeda. Saya dapat melakukan semua pekerjaan dalam file ini tetapi saya memerlukan referensi laci untuk melakukan beberapa operasi laci di file komponen. Ini kode saya, Bagaimana saya bisa meneruskan referensi laci ke file komponen lain untuk menggunakan metode laci seperti openDrawer ().

'use strict';

    var React = require('react-native');
    var { View,
          StyleSheet,
          TouchableHighlight,
          } = React;

    var DrawerLayout = require('react-native-drawer-layout');
    var DrawerScreen = require('./DrawerScreen');
    var DrawerMenu = require('./DrawerMenu');

    var DrawerLayoutExample = React.createClass({

      render: function() {
        var navigationView = (
          <View >
               <DrawerMenu/>
          </View>
        );

        return (
          <DrawerLayout
            onDrawerSlide={(e) => this.setState({drawerSlideOutput: JSON.stringify(e.nativeEvent)})}
            onDrawerStateChanged={(e) => this.setState({drawerStateChangedOutput: JSON.stringify(e)})}
            drawerWidth={200}
            ref={(drawer) => { return this.drawer = drawer  }}
            keyboardDismissMode="on-drag"
            renderNavigationView={() => navigationView}>
            <View style={styles.container}>
 // Here is content component for drawer, need to refer drawer reference
            <DrawerScreen ></DrawerScreen>
            </View>
          </DrawerLayout>
        );
      }
    });

    var styles = StyleSheet.create({
      container: {
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
        flexDirection: 'column',
      },
     });

    module.exports = DrawerLayoutExample;

DrawerScreen.js

'use strict';
var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Dimensions,
  Image,
  TouchableHighlight,
  TextInput,
} = React;

var deviceWidth = Dimensions.get('window').width;

var DrawerScreen = React.createClass({


  render: function() {
    return (

        <View style={styles.container}>

          <Text style={styles.welcome}>Content!</Text>

          <TouchableHighlight onPress={() => this.state.openDrawer()}>
            <Text>Open drawer</Text>
          </TouchableHighlight>
          <TextInput style={styles.inputField} />
        </View>
    );
  },

});

var styles = StyleSheet.create({
   container: {
      alignItems: 'center',
      justifyContent: 'center',
      flex: 1,
          flexDirection: 'column',
    },
    inputField: {
      backgroundColor: '#F2F2F2',
      height: 40,
    },
});

Saat ini saya menggunakan redux untuk berlangganan dan menyimpan mediaqueries, sehingga komponen dapat memutuskan untuk merender secara berbeda misalnya di telepon.

Ini berarti bahwa jika tidak, komponen murni memerlukan langganan ke toko, dan baunya seperti itu salah bagi saya, belum lagi model subkriber Redux yang menghasilkan banyak langganan untuk sesuatu yang jarang berubah.

Saya pikir dalam konteks kasus ini adalah tempat yang jauh lebih baik untuk menyimpannya, tetapi masalah ini mencegah saya untuk menggunakannya.

@wmertens ini adalah sesuatu yang hanya perlu dilakukan di componentDidMount kan?

@cauburtin tidak sama sekali, pengguna dapat memilih bahasa lain kapan saja, dan kapan saja pengguna dapat mengubah ukuran browser…

untuk mengubah ukuran, Anda dapat mendengarkan di componentDidMount, untuk bahasa yang akan saya render ulang semuanya

Saya lebih suka tidak mengulangi semua logika pengubahan ukuran ketika saya memiliki sesuatu yang keren seperti file
actioncreator redux yang mendengarkan seluruh apo dan bekerja di sisi server
terlalu…
Saya memiliki state.responsive.isPhone / isPrerender / screenwidth dll. Di server,
Saya mengirim berdasarkan agen pengguna. Rapi.

Pada Jum, 29 Apr 2016, 16.52 Cyril Auburtin [email protected]
menulis:

untuk mengubah ukuran, Anda bisa mendengarkan di componentDidMount, untuk bahasa yang saya mau
merender ulang semuanya

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung atau lihat di GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215742327

Wout.
(diketik di ponsel, alasan singkatnya)

Tapi ya, kunci sederhana = {lang} di bagian atas pohon sudah cukup untuk
bahasa. Tidak begitu bagus untuk situs dengan animasi.

Pada Jum, 29 Apr 2016, 18.07 Wout Mertens wout. [email protected] menulis:

Saya lebih suka tidak mengulangi semua logika pengubahan ukuran ketika saya memiliki sesuatu yang keren seperti file
actioncreator redux yang mendengarkan seluruh apo dan bekerja di sisi server
terlalu…
Saya memiliki state.responsive.isPhone / isPrerender / screenwidth dll. Di
server, saya kirim berdasarkan agen pengguna. Rapi.

Pada Jum, 29 Apr 2016, 16.52 Cyril Auburtin [email protected]
menulis:

untuk mengubah ukuran, Anda bisa mendengarkan di componentDidMount, untuk bahasa yang saya mau
merender ulang semuanya

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung atau lihat di GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215742327

Wout.
(diketik di ponsel, alasan singkatnya)

Wout.
(diketik di ponsel, alasan singkatnya)

Saya seperti Anda, tetapi pendengar acara mengubah ukuran sebenarnya murah, menurut saya tidak buruk memiliki banyak pendengar yang sama

Tidak, saya tidak ragu bahwa harganya murah, hanya saja jauh lebih mudah
untuk menulis this.context.isPhone daripada mengelola penangan pengubah ukuran.

Pada hari Jumat, 29 Apr 2016 jam 18.38 Cyril Auburtin [email protected]
menulis:

Saya seperti Anda, tapi pendengar mengubah ukuran acara sebenarnya murah, saya tidak
berpikir itu buruk untuk memiliki banyak tipe pendengar yang sama

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung atau lihat di GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215797819

Wout.
(diketik di ponsel, alasan singkatnya)

Masalahnya adalah react-redux mengembalikan === ReactElement untuk memberi sinyal "tidak ada pembaruan" dari metode render. Namun sebenarnya pintasan ini hanya dapat diakses jika konteksnya juga ===, yang tidak dapat dikontrol dari komponen. Saya tidak sepenuhnya yakin mengapa ini dilakukan dengan cara ini. Mungkin pertanyaan untuk orang-orang react-redux.

Untuk bekerja dengan Redux, lihat https://github.com/reactjs/react-router/issues/470 dan diskusi lanjutan di PR.

Pada titik tertentu, kami akan benar-benar menyelesaikan https://github.com/reactjs/react-router/issues/3484 untuk mempermudah penggunaan perpustakaan lain, tetapi ini lebih sulit daripada yang kami duga.

Perhatikan tentang solusi yang saat ini digunakan oleh react-router. Ini berfungsi tetapi merupakan peretasan yang membuat frustrasi. Ini mengharuskan kita mengubah konteks di tempat atau mengharuskan pengguna mempertahankan identitas referensial antara objek konteks mereka.

Tidak ada yang bagus, tetapi masalah sebenarnya adalah bahwa konteks wormholing di sekitar hierarki komponen merusak salah satu bit terbaik dari model komponen React untuk aliran data, yaitu bahwa apa pun yang berada di tengah (dengan otoritas) dapat menyesuaikan konteks saat berjalan. . Dengan melewatkan konteks melalui komponen "out of band" perlu menggunakan mekanisme yang berbeda untuk memetakan konteks ke anak-anak, atau tidak melakukannya. Memang ini bukan kasus penggunaan _common_, tapi itu menjelaskan semua penggunaan konteks

Di antara dua pendekatan itu setidaknya _somewhat_ generik ... yang terbaik yang bisa kita lakukan untuk saat ini, saya pikir 😛

yes inded: P, hanya mencatat bahwa ini masih kurang optimal dan bukan pengganti yang baik untuk memperbaiki cara kerja konteks secara umum

@jquense Tidak bisakah komponen di tengah mendeklarasikan contextTypes untuk mendengarkan objek konteks dari atas, dan childContextTypes / getChildContext() untuk memberikan salinan modifikasi dari konteks tersebut ke keturunannya?

Komponen @arylantell perlu ikut serta ke setiap bagian konteks yang mereka minta. Tidak ada cara untuk mendeklarasikan contextTypes untuk meneruskan keseluruhan konteks grosir ke sebuah komponen.

n dalam kasus apa pun maksud saya adalah bahwa menyesuaikan bit konteks _adalah_ mungkin dan fitur konteks yang hebat, yang dipecah oleh solusi untuk masalah ini

@ 1000hz Tentu, tapi dia berbicara tentang "menyesuaikan bagian konteks saat berjalan". Dalam skenario itu, Anda tidak perlu mendapatkan konteks "keseluruhan", hanya bagian mana saja yang ingin Anda timpa.

@DarylCantrell Ups, saya salah membaca maksud Anda.

Saya telah mengirimkan permintaan penarikan untuk masalah ini: # 7213

(dari permintaan tarik)
Saya menggunakan konteks untuk menyebarkan informasi lokal dan perutean. Masalah saya adalah bahwa beberapa komponen murni menghentikan rendering subpohon ketika konteksnya berubah (karena komponen murni hanya memeriksa status dan alat peraga). Ini adalah masalah bagi banyak orang sesuai terbitan # 2517.

Saya beralasan bahwa tidak menutupi konteks untuk komponen perantara akan lebih baik daripada menutupi, dan konteksTipe yang ditentukan hanya akan digunakan untuk memvalidasi, bukan untuk pemfilteran. Ini mirip dengan cara kerja propTypes, di mana properti yang ditentukan divalidasi tetapi properti yang tidak ditentukan masih tersedia untuk komponen. Saya telah memperbarui tes untuk mencerminkan pembaruan ini.

Karena komponen yang tidak tertarik pada konteks biasanya tidak akan menggunakan argumen konteks, tidak menutupi konteks tidak akan menyebabkan komponen yang ada rusak, kecuali komponen tersebut secara eksplisit memeriksa bahwa parameter konteks tidak ditentukan. Namun, hal ini akan menciptakan peluang untuk komponen murni yang disempurnakan, misalnya ContextAwarePureComponent yang akan membandingkan status, alat peraga, dan konteks di shouldComponentUpdate, memungkinkan konteks diperbarui untuk menyebabkan pembuatan ulang komponen murni.

Saya sedang menjalankan pengembangan dengan tambalan ini, menggunakan radium dan beberapa komponen react-bootstrap, dan tidak mengalami masalah apa pun

Halo @bvella , saya rasa yang Anda maksud permintaan tarik ini: # 7213, bukan 7212.

@DarylCantrell Anda benar, terima kasih

Saya pikir https://github.com/facebook/react/pull/7213 / https://github.com/facebook/react/pull/7225 , adalah bagus dan harus disesuaikan

Pemahaman saya adalah bahwa konteksnya seperti variabel global dan karenanya harus dibatasi penggunaannya;
namun, itu tidak berarti bahwa pengguna harus membuat deklarasi sebelum mereka dapat mengakses variabel global;
Variabel global harus selalu dapat diakses terlepas dari apakah Anda mendeklarasikan atau tidak;

deklarasi contextType seharusnya hanya berfungsi untuk tujuan validasi, seperti propTypes

sekali lagi, mohon dipikirkan karena itu menyebabkan banyak masalah bagi kami
(Saya menggunakan react Relay dan menyembunyikan semua objek konteks)

Saya berkomentar di https://github.com/facebook/react/pull/7225#issuecomment -276618328, dengan alasan bahwa konteks seharusnya memperbarui semuanya, dan sCU hanya berfungsi untuk memutuskan apakah komponen itu perlu dirender ulang ; anak-anaknya akan diverifikasi.

Melakukan pembaruan konteks dengan cara itu memakan biaya, tetapi lebih murah daripada merender paksa seluruh struktur yang saat ini merupakan satu-satunya cara untuk mendapatkan pembaruan konteks untuk membuatnya ke semua komponen. Konteks tidak seharusnya banyak berubah; ada opsi yang lebih baik untuk pembaruan yang cepat berubah (misalnya Redux).

Apakah ada solusi untuk saat ini?

Seperti yang kita ketahui dari utas ini, solusi yang ada pada dasarnya rusak.
Kami tidak dapat memperbaiki API saat ini tanpa memperlambat semua aplikasi (yang ingin kami hindari :-).

Oleh karena itu, kami mengusulkan API baru yang menangani kasus penggunaan yang sama tetapi tidak memiliki kekurangan desain tersebut. Rencananya adalah agar API ada secara berdampingan, dan nanti untuk menghapus API lama secara bertahap ketika orang telah bermigrasi.

Lihat diskusi: https://github.com/reactjs/rfcs/pull/2

@acdlite baru saja mendapatkan PR dengan API konteks baru: https://github.com/facebook/react/pull/11818.

Saya pikir kita bisa menganggap ini tertutup. API baru tidak memiliki masalah ini. API lama tidak dapat diperbaiki, dan kami akan menghentikannya di beberapa titik setelah perpustakaan utama meningkatkan ke API baru.

API baru akan tersedia dan didokumentasikan di salah satu rilis React 16.x minor berikutnya.

@gaearon Tidak yakin apakah Anda sering mendengar ini, tetapi: kalian melakukan pekerjaan dengan baik dan saya menghargai pekerjaan Anda. 🍺

Apakah halaman ini membantu?
0 / 5 - 0 peringkat