Saya tahu bahwa Bereaksi dapat melakukan pembaruan status secara tidak sinkron dan sekaligus untuk optimasi kinerja. Karena itu Anda tidak pernah bisa mempercayai keadaan yang akan diperbarui setelah menelepon setState
. Tapi yang dapat Anda percaya Bereaksi untuk memperbarui negara dalam urutan yang sama seperti setState
yang disebut untuk
- komponen yang sama?
- komponen yang berbeda?
Pertimbangkan mengklik tombol dalam contoh berikut:
1. Apakah ada kemungkinan bahwa a salah dan b benar untuk:
class Container extends React.Component {
constructor(props) {
super(props);
this.state = { a: false, b: false };
}
render() {
return <Button onClick={this.handleClick}/>
}
handleClick = () => {
this.setState({ a: true });
this.setState({ b: true });
}
}
2. Adakah kemungkinan bahwa a salah dan b benar untuk:
class SuperContainer extends React.Component {
constructor(props) {
super(props);
this.state = { a: false };
}
render() {
return <Container setParentState={this.setState.bind(this)}/>
}
}
class Container extends React.Component {
constructor(props) {
super(props);
this.state = { b: false };
}
render() {
return <Button onClick={this.handleClick}/>
}
handleClick = () => {
this.props.setParentState({ a: true });
this.setState({ b: true });
}
}
Perlu diingat bahwa ini adalah penyederhanaan ekstrim dari use case saya. Saya menyadari bahwa saya dapat melakukan ini secara berbeda, misalnya memperbarui kedua param negara bagian pada saat yang sama dalam contoh 1, serta melakukan pembaruan keadaan kedua dalam panggilan balik ke pembaruan keadaan pertama dalam contoh 2. Namun, ini bukan pertanyaan saya, dan saya hanya tertarik jika ada cara yang terdefinisi dengan baik bahwa React melakukan pembaruan status ini, tidak ada yang lain.
Setiap jawaban yang didukung oleh dokumentasi sangat dihargai.
sumber
Jawaban:
Saya mengerjakan React.
TLDR:
Iya.
Iya.
The rangka update selalu dihormati. Apakah Anda melihat kondisi antara "di antara" mereka atau tidak tergantung pada apakah Anda berada di dalam kumpulan atau tidak.
Saat ini (Bereaksi 16 dan sebelumnya), hanya pembaruan di dalam penangan aktivitas Bereaksi yang di-batch secara default . Ada API yang tidak stabil untuk memaksa batching di luar event handler untuk kasus yang jarang terjadi saat Anda membutuhkannya.
Dalam versi yang akan datang (mungkin Bereaksi 17 dan yang lebih baru), Bereaksi akan mengelompokkan semua pembaruan secara default sehingga Anda tidak perlu memikirkan hal ini. Seperti biasa, kami akan mengumumkan perubahan apa pun tentang ini di blog Bereaksi dan dalam catatan rilis.
Kunci untuk memahami ini adalah bahwa tidak peduli berapa banyak
setState()
panggilan dalam berapa banyak komponen yang Anda lakukan di dalam penangan peristiwa Bereaksi , mereka hanya akan menghasilkan render tunggal pada akhir acara . Ini sangat penting untuk kinerja yang baik dalam aplikasi besar karena jikaChild
danParent
setiap panggilansetState()
saat menangani acara klik, Anda tidak ingin merender ulangChild
dua kali.Dalam kedua contoh Anda,
setState()
panggilan terjadi di dalam pengendali event Bereaksi. Oleh karena itu mereka selalu memerah bersama di akhir acara (dan Anda tidak melihat negara perantara).Pembaruan selalu dangkal digabung dalam urutan terjadinya . Jadi, jika pembaruan pertama adalah
{a: 10}
, yang kedua adalah{b: 20}
, dan yang ketiga adalah{a: 30}
, keadaan yang diberikan akan{a: 30, b: 20}
. Pembaruan yang lebih baru untuk kunci negara yang sama (misalnya sepertia
dalam contoh saya) selalu "menang".The
this.state
objek diperbarui ketika kita kembali membuat UI pada akhir bets. Jadi, jika Anda perlu memperbarui negara berdasarkan keadaan sebelumnya (seperti menambah penghitung), Anda harus menggunakansetState(fn)
versi fungsional yang memberi Anda keadaan sebelumnya, alih-alih membaca darithis.state
. Jika Anda penasaran dengan alasan untuk ini, saya jelaskan secara mendalam dalam komentar ini .Dalam contoh Anda, kami tidak akan melihat "keadaan perantara" karena kami berada di dalam penangan peristiwa Bereaksi tempat batching diaktifkan (karena Bereaksi "tahu" ketika kita keluar dari peristiwa itu).
Namun, baik dalam Bereaksi 16 dan versi sebelumnya, belum ada batching secara default di luar penangan event Bereaksi . Jadi, jika dalam contoh Anda, kami memiliki penangan respons AJAX alih-alih
handleClick
, masingsetState()
- masing akan segera diproses begitu terjadi. Dalam hal ini, ya, Anda akan melihat kondisi perantara:Kami menyadari tidak nyaman bahwa perilakunya berbeda tergantung pada apakah Anda berada dalam event handler atau tidak . Ini akan berubah di versi Bereaksi masa depan yang akan mengelompokkan semua pembaruan secara default (dan menyediakan API keikutsertaan untuk menyiram perubahan secara sinkron). Sampai kami beralih perilaku default (berpotensi dalam Bereaksi 17), ada API yang dapat Anda gunakan untuk memaksa batching :
React event handler internal semuanya dibungkus
unstable_batchedUpdates
dan itulah sebabnya mereka dikelompokkan secara default. Perhatikan bahwa membungkus pembaruanunstable_batchedUpdates
dua kali tidak berpengaruh. Pembaruan memerah ketika kita keluar dariunstable_batchedUpdates
panggilan terluar .API itu "tidak stabil" dalam arti bahwa kami akan menghapusnya ketika batching sudah diaktifkan secara default. Namun, kami tidak akan menghapusnya dalam versi kecil, sehingga Anda dapat dengan aman mengandalkannya sampai Bereaksi 17 jika Anda perlu memaksa batching dalam beberapa kasus di luar React event handler.
Singkatnya, ini adalah topik yang membingungkan karena Bereaksi hanya kumpulan di dalam penangan acara secara default. Ini akan berubah di versi masa depan, dan perilaku akan lebih mudah. Tapi solusinya bukan batch lebih sedikit , itu untuk batch lebih banyak secara default. Itu yang akan kita lakukan.
sumber
obj.a = true; obj.b = true
) dan kemudian pada akhirnya lakukan sajathis.setState(obj)
. Ini aman terlepas dari apakah Anda berada di dalam pengendali acara atau tidak. Mungkin trik yang rapi jika Anda sering membuat kesalahan dengan mengatur keadaan beberapa kali di luar event handler.componentDidUpdate
dan callback daur hidup lainnya pada React 16? Terima kasih sebelumnya!Ini sebenarnya pertanyaan yang cukup menarik tetapi jawabannya tidak boleh terlalu rumit. Ada artikel bagus tentang media yang memiliki jawaban.
1) Jika Anda melakukan ini
Saya tidak berpikir bahwa akan ada situasi di mana
a
akantrue
danb
akanfalse
karena batching .Namun, jika
b
tergantung padaa
maka mungkin memang ada situasi di mana Anda tidak akan mendapatkan keadaan yang diharapkan.Setelah semua panggilan di atas diproses
this.state.value
akan menjadi 1, bukan 3 seperti yang Anda harapkan.Ini disebutkan dalam artikel:
setState accepts a function as its parameter
Ini akan memberi kita
this.state.value === 3
sumber
this.state.value
diperbarui baik dalam event handler (di manasetState
adalah batched) dan callback AJAX (manasetState
yang tidak batched). Dalam event handler, saya akan menggunakanupdater function
untuk selalu memastikan bahwa saya memperbarui status menggunakan status yang saat ini diperbarui disediakan oleh fungsi. Haruskah saya gunakansetState
dengan fungsi pembaru di dalam kode panggilan balik AJAX bahkan jika saya tahu itu tidak batched? Bisakah Anda menjelaskan penggunaansetState
callback AJAX dengan atau tanpa menggunakan fungsi updater? Terima kasih!setState
akan dieksekusi tetapi yang terakhir akan menang.Beberapa panggilan selama siklus yang sama dapat dikumpulkan bersamaan. Misalnya, jika Anda berupaya menambah jumlah item lebih dari satu kali dalam siklus yang sama, itu akan menghasilkan yang setara dengan:
https://reactjs.org/docs/react-component.html
sumber
seperti dalam doc
itu akan membentuk sebelumnya perubahan seperti dalam antrian ( FIFO : First In First Out) panggilan pertama akan menjadi yang pertama untuk membentuk sebelumnya
sumber