React: Haruskah menyetel status di dalam peristiwa diskrit menyebabkan pembersihan berjalan?

Dibuat pada 5 Mar 2019  ·  3Komentar  ·  Sumber: facebook/react

Bug ini cukup membingungkan:

https://twitter.com/kentcdodds/status/1102659818660102145

Saya pikir itu terjadi karena fn dijadwalkan oleh setInterval(fn, 0) melompat di depan [running] efek pembersihan yang disebabkan oleh setRunning(false) . Jadi interval masih menyala, menimpa setLapse(0) yang terjadi selama acara dengan setLapse(someValue) .

Ini mengingatkan saya pada masalah yang dijelaskan di https://github.com/facebook/react/issues/14750#issuecomment -460409609, atau setidaknya sebagian darinya:

Faktanya, masalah ini ada bahkan untuk penekanan tombol React biasa (dan acara "diskrit" lainnya). Solusi untuk itu adalah menghilangkan efek pasif sebelum kita mendapatkan peristiwa diskrit.

Tapi di sini, sepertinya ini tidak akan cukup karena efeknya terbalik sebagai akibat dari klik, bukan sebelumnya. Jadi haruskah setState di dalam event diskrit juga menyiram efek pasif? Sepertinya tidak. (Itu akan mengalahkan tujuan menunda mereka.)

Jadi ini berfungsi seperti yang dirancang, dan perbaikannya hanya useLayoutEffect ketika waktunya penting? Atau solusi rAF?

Hooks Question

Komentar yang paling membantu

Salah satu pendekatan adalah mengirimkan reset hanya sekali timer benar-benar berhenti, yaitu pada efeknya. Jika Anda ingin selalu menampilkan nol dalam bingkai yang sama, maka Anda selalu dapat menampilkan nol saat menjalankan salah.

Namun, seperti hampir selalu, ini lebih baik dimodelkan sebagai peredam. Peredam dapat dengan mudah menolak pembaruan untuk selang ketika dianggap dalam keadaan berhenti dan juga melakukan logika untuk benar-benar mengatur ulang.

Semua 3 komentar

Masalahnya adalah bahwa pengatur waktu itu sendiri bukanlah peristiwa yang terpisah. Peristiwa diskrit hanya dijamin dalam kaitannya dengan peristiwa diskrit lainnya. Saya tidak berpikir itu yang Anda inginkan di sini.

Menghentikan timer adalah operasi asinkron karena semua status yang ditetapkan adalah asinkron. Jadi sesuatu yang lain bisa masuk sebelum memerah.

Ini adalah kasus di mana useLayoutEffect sebenarnya tidak sepenuhnya memperbaiki masalah. Tentu saja tidak dalam mode bersamaan, tetapi ini juga tidak jelas dalam mode sinkronisasi. Jika itu bukan pengatur waktu tetapi katakanlah acara fokus, maka itu dapat menyala dalam batch sebelum ini memerah yang akan memiliki masalah yang sama.

setRunning(false); // I would like to add a stop of this timer to the queue to be performed later
setLapse(0); // I would like to add an operation to set lapse to zero later
// lots of random stuff that can happen before the batch flushes
// This might also queue an operation to set lapse to something else
// actual rendering
// If concurrent mode, lots of other random stuff that can happen while rendering
// This might also queue an operation to set lapse to something else
// Actually do all that work in order

Ini semua tentang urutan apa yang ditambahkan ke antrian.

Salah satu pendekatan adalah mengirimkan reset hanya sekali timer benar-benar berhenti, yaitu pada efeknya. Jika Anda ingin selalu menampilkan nol dalam bingkai yang sama, maka Anda selalu dapat menampilkan nol saat menjalankan salah.

Namun, seperti hampir selalu, ini lebih baik dimodelkan sebagai peredam. Peredam dapat dengan mudah menolak pembaruan untuk selang ketika dianggap dalam keadaan berhenti dan juga melakukan logika untuk benar-benar mengatur ulang.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat