React-window: Versi 2 berubah

Dibuat pada 29 Jul 2019  ·  44Komentar  ·  Sumber: bvaughn/react-window

Ini adalah masalah umum untuk membagikan rencana saya untuk rilis versi 2.0 mendatang dari react-window .

Umpan balik dihargai dan akan dipertimbangkan. Saya meminta Anda memahami jika saya tidak dapat mengakomodasi semua permintaan. Saya akan mencoba melakukan yang terbaik untuk mempertimbangkan permintaan fitur terhadap ukuran bundel, kinerja runtime, dan masalah pemeliharaan.

Saya berharap bahwa peningkatan dari versi 1 ke 2 mungkin memerlukan perubahan kode yang substansial , banyak di antaranya tidak dapat diotomatiskan dengan mod kode. Oleh karena itu, khususnya untuk kode aplikasi, saya menyarankan agar tidak mengupgrade kode yang ada kecuali Anda memiliki alasan yang kuat (misalnya Anda memerlukan dukungan untuk konten dengan ukuran dinamis).

Saya juga akan melanjutkan dan menyematkan dokumen saat ini ke domain react-window-v1.now.sh sehingga tidak akan hilang ketika saya memperbarui untuk versi 2.


Daftar Isi:
  • Mendukung lebih sedikit komponen
  • Gunakan API alat peraga render
  • Tidak ada lagi dukungan daftar horizontal
  • Hanya jaringan yang mendukung RTL
  • Perubahan pada waktu panggilan balik onScroll

    * Perubahan / penghentian lainnya

Lebih sedikit komponen

Salah satu cara untuk membantu mengelola kompleksitas adalah dengan mengurangi jumlah komponen yang didukung library . Saat ini saya berencana hanya mendukung jenis komponen berikut di versi 2:

  • SimpleList (sebelumnya FixedSizeList )

    • Komponen daftar yang sangat dioptimalkan ini harus digunakan ketika tinggi baris ditetapkan (dan diketahui sebelumnya).

  • List (sebelumnya DynamicSizeList )

    • Daftar ini harus digunakan untuk konten berukuran dinamis (mis. Obrolan, umpan berita). Ini membutuhkan ResizeObserver API (atau polyfill).

  • Grid (sebelumnya VariableSizeGrid )

    • Komponen ini harus digunakan untuk data tabular (misalnya spreadsheet) yang harus divirtualisasi sepanjang sumbu vertikal dan horizontal. Ini mendukung baris dan kolom ukuran variabel, tetapi tidak mendukung pengukuran dan pembaruan ukurannya secara otomatis.


Render alat peraga

Salah satu perubahan besar dari react-virtualized menjadi react-window adalah keputusan untuk memperlakukan children sebagai elemen React (misalnya React.createElement(children, props)) ) daripada sebagai alat peraga render (misalnya children(props) ).

Ada beberapa motivasi untuk melakukan ini:

  • React menyediakan solusi built-in untuk memoization (misalnya React.memo , useMemo , shouldComponentUpdate ) jadi saya tidak perlu mengimplementasikan abstraksi caching saya sendiri untuk penyaji item.
  • API seperti hook dan suspense "bekerja" di dalam perender item.
  • Kunci dapat dikelola dengan react-window tanpa memerlukan render prop untuk meneruskannya (dan tanpa memerlukan panggilan cloneElement ).

Sayangnya, ada juga beberapa kerugian:

  • Penyaji item sebaris dikenakan biaya tinggi. Karena "type" (definisi fungsi) dibuat ulang setiap kali komponen induk dirender, React melepas secara mendalam dan memasang kembali pohon yang dirender. Artinya, dokumen perlu mengajari orang untuk tidak menggunakannya meskipun seringkali lebih nyaman.
  • Karena fungsi sebaris tidak dapat digunakan untuk menutup cakupan lokal, lebih rumit bagi perender item untuk berbagi status dengan orang tua, memerlukan API seperti itemData dan ekspor perbandingan khusus areEqual .

Setelah mempertimbangkan pro dan kontra di atas, saya memutuskan untuk mengonversi ke pendekatan alat peraga render untuk react-window juga. Artinya, contoh rumit seperti ini dapat ditulis ulang dengan lebih mudah:

const Example = ({ height, items, toggleItemActive, width }) => (
  <List
    height={height}
    itemCount={items.length}
    itemRenderer={({ index, key, style }) => {
      const item = items[index];
      return (
        <div key={key} onClick={() => toggleItemActive(index)} style={style}>
          {item.label} is {item.isActive ? "active" : "inactive"}
        </div>
      );
    }}
    itemSize={35}
    width={width}
  />
);

Tidak ada lagi dukungan daftar horizontal

Sebelumnya, daftar komponen mendukung mode tata letak horizontal dan vertikal. Untuk menyederhanakan implementasi dan pemeliharaan, dan karena kasus penggunaan yang sangat umum adalah daftar vertikal, saya akan menghapus dukungan untuk layout="horizontal" .


Dukungan RTL

Komponen kisi akan terus mendukung direction="RTL" , tetapi daftar tidak akan (karena mereka hanya akan mendukung tata letak vertikal). Pertukaran ini dilakukan untuk memungkinkan daftar menjadi lebih kecil dan lebih mudah dikelola.


onItemsRendered dan onScroll perubahan panggilan balik

Komponen daftar dan kisi saat ini mendukung alat peraga callback onItemsRendered dan onScroll . Callback ini dipanggil selama fase komit (setelah daftar atau kisi menyelesaikan rendering). Hal ini dapat berguna karena selalu aman untuk melakukan efek samping (seperti logging analitik) sebagai respons terhadap callback ini, tetapi juga memiliki sisi negatifnya: pembaruan tersinkronisasi scroll apa pun harus dilakukan dalam satu detik ("cascading") render .

Versi 2 akan membuat perubahan pada callback onScroll untuk mengatasi ini. Callback onScroll akan dipanggil selama siklus pengiriman event sehingga setiap update akan digabungkan (oleh React) dengan update list atau grid itu sendiri.

Callback onItemsRendered akan diganti dengan onItemsDisplayed prop , meskipun akan terus dipanggil selama siklus komit. Perubahan ini dilakukan untuk memungkinkan komponen daftar mengoptimalkan kinerja render secara lebih agresif dengan melakukan pra-rendering pada prioritas nonaktif dan memanfaatkan API eksperimental seperti penguncian tampilan .


Perubahan / penghentian alat peraga lainnya

Ada beberapa penghentian yang menunggu keputusan (dengan peringatan DEV) yang akan dihapus:

  • innerTagName dan outerTagName untuk semua daftar dan komponen grid. (Gunakan innerElementType dan outerElementType sebagai gantinya.)
  • overscanCount , overscanColumnsCount , dan overscanRowsCount untuk komponen grid. (Gunakan overscanColumnCount dan overscanRowCount sebagai gantinya.)
  • overscanCount akan dihapus untuk komponen daftar, untuk mendukung pendekatan overscanning dinamis.
  • Nilai "horizontal" dan "vertikal" untuk direction . (Ini telah dipindahkan ke layout , tetapi mereka akan dihapus seluruhnya dalam versi 2.)
  • itemData prop (dan data prop yang sesuai diteruskan ke penyaji item) akan dihapus karena perubahan pada API render prop tidak lagi membuat ini diperlukan.
  • useIsScrolling prop (dan isScrolling prop yang sesuai diteruskan ke penyaji item) akan dihapus karena perubahan pada pra-rendering dan penguncian tampilan akan membuat ini lebih mahal untuk diterapkan.
  • Parameter perataan gulir akan sedikit berubah. Yang sebelumnya bernama "otomatis" sekarang akan diberi nama "minimal". Nilai default baru adalah "smart" (bukan "auto").

Perhatikan bahwa beberapa alat peraga yang tidak digunakan lagi di atas mungkin masih tidak relevan mengingat perubahan terencana lainnya, tetapi saya tetap mencantumkannya di sini demi kelengkapan.

👋 help wanted 💬 discussion

Komentar yang paling membantu

Daftar horizontal banyak digunakan di perangkat seluler dalam kasus kami. Kami juga menggunakannya untuk kontrol seperti carousel yang dapat digulir tanpa batas. IMO pasti punya sesuatu di ponsel.

Semua 44 komentar

Daftar horizontal banyak digunakan di perangkat seluler dalam kasus kami. Kami juga menggunakannya untuk kontrol seperti carousel yang dapat digulir tanpa batas. IMO pasti punya sesuatu di ponsel.

Terima kasih telah berbagi kasus penggunaan @istarkov. Bukannya saya tidak berpikir ada _any_ kasus penggunaan yang valid untuk jendela horizontal. Saya hanya berpikir mereka jauh lebih jarang. (Bahkan dalam kasus korsel, banyak yang menggunakan navigasi panah kiri / kanan yang tidak memerlukan jendela berbasis peristiwa "gulir".) Saya pikir itu mungkin masih merupakan rute yang lebih baik (bagi saya) untuk melepaskan dukungan untuk v2 untuk membantu mengimbangi beberapa kompleksitas yang saya rencanakan untuk diperkenalkan dengan pra-rendering, ukuran dinamis, dll.

Saya sangat senang dengan pendekatan yang lebih ramping ini yang diharapkan akan menghasilkan kode yang lebih sederhana, lebih berkinerja, dan lebih sederhana.

Bagus. Tetapi saya memiliki sedikit kekhawatiran tentang menghapus daftar ukuran variabel. Anda berencana untuk mengganti daftar ukuran variabel dengan DynamicList tetapi masalah dengan daftar dinamis yang tidak dapat Anda gulir ke item, yang mungkin merupakan fitur yang sangat berguna untuk beberapa komponen dan persyaratan semacam itu dapat muncul seiring waktu, jadi Anda tidak dapat memprediksi apakah react-window sesuai dengan kebutuhan Anda.
Masalah kedua yang saya lihat adalah kinerja daftar dinamis, jika Anda dapat memberikan kinerja yang sama untuk daftar dinamis seperti untuk daftar ukuran variabel, mungkin tidak masalah untuk melepaskannya bahkan jika Anda tidak mendukung scrollToItem, tetapi jika tidak, pengembang dapat dikunci situasi aneh di mana daftar Dinamis lambat dan tidak memiliki dukungan gulir ke item, Daftar hanya memiliki ketinggian item tetap.

Anda berencana untuk mengganti daftar ukuran variabel dengan DynamicList tetapi masalah dengan daftar dinamis yang tidak dapat Anda gulir ke item

Saya tidak berpikir ini adalah batasan yang melekat, hanya salah satu dari implementasi saat ini. Saya punya ide bagaimana saya bisa menawarkan fungsi itu. Apakah saya punya waktu untuk mengatasinya adalah pertanyaan lain: tersenyum:

Masalah kedua yang saya lihat adalah kinerja daftar dinamis, jika Anda dapat memberikan kinerja yang sama untuk daftar dinamis seperti untuk daftar ukuran variabel, mungkin tidak masalah untuk melepaskannya bahkan jika Anda tidak mendukung scrollToItem, tetapi jika tidak, pengembang dapat dikunci situasi aneh di mana daftar Dinamis lambat dan tidak memiliki dukungan gulir ke item, Daftar hanya memiliki ketinggian item tetap.

Sulit untuk mengatakan apakah itu akan bekerja dengan baik. Sepertinya daftar dinamis harus melakukan lebih banyak pekerjaan sehingga kemungkinan besar itu tidak akan berfungsi dengan baik. Mungkin perbedaannya akan signifikan, mungkin juga tidak. Saya ingin dapat mendukung beberapa hal yang saat ini tidak saya miliki, dan saya rasa saya perlu memotong cakupan untuk menambahkan fitur baru. Jika saat ini Anda senang dengan daftar variabel, tidak ada alasan untuk meningkatkan ke v2 (setidaknya dalam waktu dekat).

@bvaughn Ini terlihat seperti dokumentasi bagi saya!
Apakah Anda sudah mengerjakan ini sejak musim panas lalu? ;-)

Pada catatan yang lebih serius - saya pikir alat peraga render masuk akal dalam konteks ini, meskipun saya bukan penggemar.

Tidak, saya menulis pagi ini 😝 Saya kelelahan.

Saya pikir alat peraga render masuk akal dalam konteks ini, meskipun saya bukan penggemar.

Bisakah Anda menjelaskan mengapa Anda bukan penggemar?

Dapatkah dukungan daftar / kisi horizontal masuk akal sebagai fitur keikutsertaan seperti AutoSizer (react-virtualized-auto-sizer)?

Saya telah menggunakan react-virtualized dan react-window untuk daftar horizontal, dan menemukan API react-window jauh lebih sederhana. Meskipun saya tidak mengerti perlunya penghentian dengan harapan untuk API yang lebih sederhana.

Dukungan jaringan masih direncanakan. Memilih dukungan horizontal, tidak juga. Saya rasa itu tidak masuk akal.

@bvaughn Saya biasanya menikmati alat peraga render dan mereka akan menyelesaikan masalah yang telah Anda uraikan, tetapi saya pikir mereka mendorong fungsi inline yang mungkin atau mungkin tidak berisi banyak logika bersarang. 🤔 Namun, kesalahan apa pun di sini jatuh pada pengguna. 🙂

dapatkah Anda menyadari jaringan batu?

@nikitapilgrim Tidak. Saya sarankan hanya menggunakan komponen Masonry dari react-virtualized

https://github.com/bvaughn/react-virtualized/blob/master/docs/Masonry.md

terima kasih, tapi kerjanya hanya dengan react-virtualized?

@nikitapgrim Yup. 👍
React-virtualized mendukung banyak fitur, sedangkan react-window tidak.

Cakupan jendela reaksi dikurangi secara drastis, untuk fokus pada pembuatan paket yang lebih kecil dan lebih cepat . 😉

Jika Anda memerlukan fitur dari react-virtualized, saya sarankan Anda tetap menggunakannya - ini masih perpustakaan yang bagus!

Saya menemukan react-window karena saya sedang mencari solusi untuk masalah react-virtualized babel 7 . Saya menggunakan komponen react-virtualized Masonry tetapi tidak bisa lagi setelah memutakhirkan babel .

Ini bukan tempat untuk melaporkan masalah dengan react-virtualized.

Setuju @bvaughn. Namun Anda dan @babangsund membalas @nikitapilgrim di atas bahwa komponen Masonry tidak akan diperkenalkan di react-window dan sebaliknya akan menggunakan react-virtualized . Namun, jika pengguna menggunakan [email protected] dan [email protected] (misalnya dengan create-react-app ), react-virtualized belum tentu berfungsi.

Saya pikir itu adalah info yang berguna bagi orang lain yang mengalami lubang kelinci yang sama.
¯ \ _ (ツ) _ / ¯

hai saya ingin menggunakan daftar ukuran dinamis di mana saya dapat mengunduh versi 2 atau saya harus menggunakan react virtualise?
image

ini adalah tampilan daftar saya dengan daftar ukuran variabel

Ini bukan masalah dukungan umum. Tolong beri komentar tentang topik.

Umpan balik sangat dihargai

Saya menggunakan react-window untuk produk seperti trello dan berikut beberapa pemikirannya:

Render alat peraga

Ini sepertinya perubahan yang bagus karena kesederhanaan dan untuk menghindari sisi negatif yang disebutkan. Selain itu, api akan lebih mirip dengan FlatList react-native. Saya ingat membaca diskusi di https://github.com/bvaughn/react-window/issues/85.

Lebih sedikit komponen
Tidak ada lagi dukungan daftar horizontal

Saya sangat memilih menentang penghapusan horizontal dukungan dan VariableSizeList . Seperti yang bisa Anda bayangkan, ini adalah dua alat utama yang saya gunakan. Apakah penerapannya benar-benar terlalu membebani? Jika tidak, saya harap Anda dapat mempertimbangkan kembali dan menyimpannya.

Saya tidak memiliki pendapat yang kuat terkait dengan perubahan lainnya. Penghapusan overscanCount memang sedikit mengkhawatirkan saya, tetapi saya belum menghadapi kasus penggunaan di mana nilai khusus diperlukan, jadi mungkin baik-baik saja.

Hei @bughn! Terima kasih untuk paket ini! Saya ingin memasukkan versi 2 dalam proyek saya di tempat kerja. Apakah Anda memiliki perkiraan kasar kapan ini akan dirilis?

Terima kasih untuk pustaka ini, dan membagikan rencana Anda untuk rilis di masa mendatang, sangat membantu untuk membantu kami mengurangi utang teknis.

Adakah cara "sederhana" untuk memiliki perilaku WindowScroller menggunakan react-window dan yang lebih baru pada versi 2?

Jika tidak mungkin, apakah ini di luar batasan versi 2 ini? atau bisakah ini ditambahkan nanti?

Konteks saya adalah tata letak saya menyertakan footer, dan menggunakan pendekatan modern seperti DynamicSizeList akan memperkenalkan scroll bar kedua (satu untuk halaman dan satu untuk daftar produk)

Paket hebat. Menunggu daftar ketinggian dinamis secara default - saat ini saya menulis banyak logika khusus untuk meneruskan ketinggian baris yang diberikan kembali ke daftar induk. Semoga dengan versi baru ini saya bisa menghilangkan logika tersebut. Terima kasih atas pekerjaan Anda dalam hal ini!

@ltkn @ltkn

Sudah ada cara menggunakan penggulung jendela:
https://github.com/bvaughn/react-window/issues/30#issuecomment -428868071

Bagaimana melakukan Gulir tak terbatas di kedua arah, kiri atau kanan !!!

Jika kita memiliki WindowScroller tanpa bergantung pada react-virtualized itu akan bagus. Karena tujuan di balik react-window membuatnya jauh lebih efisien dan lebih sedikit kode dibandingkan dengan react-virtualized Jadi, saya tidak ingin menggunakan WindowScroller dari react-virtualized . Alih-alih mencari paket terpisah seperti react-virtualized-auto-sizer .

Terima kasih sebelumnya.

@prabus hm ..
Apa keuntungan dari paket terpisah?

Telah bermain-main dengan DynamicSizeList baru. Sangat keren! Saya pikir peningkatan besar akan memasukkan 'ttb' dan 'btt' (top-to-bottom, bottom-to-top) dalam jenis arah. Saat ini tidak ada cara bersih untuk mengimplementasikan daftar yang bergulir ke atas, tetapi setiap arah lainnya didukung.

@toddmacintyre Saya tidak dapat menemukan versi ini 2. Adakah yang bisa memandu saya?

@muhammedmagdi npm install react-window@next

Akan sangat brilian jika versi 2 dapat mendukung struktur DOM yang dibutuhkan oleh spesifikasi di sini - https://www.w3.org/TR/wai-aria-1.1/#grid karena # 217 masih menjadi masalah bagi kami. Sejauh yang saya tahu proposal Anda untuk versi 2 sekarang tidak.

@mjurkowski @bvaughn yarn add react-window@next memasang 1.6.0-alpha.1 . Juga ketika mencoba menjalankan contoh kotak pasir daftar dinamis https://react-window-next.now.sh/#/examples/list/dynamic -size itu melempar Error importing GitHub repository: Could not find package.json

Bagaimana kalau melewatkan index di Grid juga - sambil melakukannya? :)

Bagian dari aplikasi kita membutuhkan grid dengan header kolom lebar variabel. Kami telah mencapai itu dengan menggunakan daftar ukuran variabel horizontal yang digabungkan dengan kisi dan menyinkronkan pengguliran keduanya.

Menghapus daftar horizontal akan mencegah kita membuat UI tersebut (atau setidaknya kita harus menulis ulang untuk menggunakan 2 grid di mana grid header kolom memiliki satu baris.

Produk selanjutnya terlihat luar biasa. Tapi saya membutuhkan horizontal dan vertikal, jadi FYI saya buat sendiri: https://www.npmjs.com/package/react-infinite-grid-scroller. Menggunakan tata letak kisi, kait reaksi, IntersectionObserver, dan requestIdleCallback.

Umpan balik diterima.

Saya merasa bahwa mendukung elemen lengket akan menjadi tambahan yang bagus untuk jendela reaksi. Ini adalah kasus penggunaan yang cukup umum dan akan langsung diterapkan untuk daftar dan kisi.

API tersebut akan terlihat seperti ini:

<Grid
    // First 2 columns are sticky
    stickyLeft={2}
    // Last column is not sticky (default value)
    stickyRight={0}
    // First and last rows are sticky
    stickyTop={1}
    stickyBottom={1}
/>

Dua elemen kunci untuk membuat kelengketan bekerja adalah:

  1. hanya lepaskan sel yang lengket jika berada di luar jendela dalam sumbu, sel tersebut tidak lengket
  2. gunakan position: sticky bukan absolute , dan gunakan margin-x sebagai ganti left dan top untuk sumbu yang tidak lengket

Biaya untuk fitur hebat seperti itu tampaknya masuk akal:

  • Jejaknya minimal
  • Tidak ada dampak besar pada kinerja (hanya merender beberapa baris / kolom tambahan)
  • Dukungan browser sangat bagus, dan mereka yang tidak mendukung position: sticky hanya melihat versi normal

Jika menurut Anda kasus penggunaan ini terlalu spesifik untuk didukung sebagaimana adanya, kompromi yang baik adalah hanya mendukung poin 1. Mampu menentukan apakah sel harus dirender atau tidak akan memungkinkan untuk menerapkan kelekatan dengan mudah.

Saya akan dengan senang hati membantu jika diperlukan.

tidak mendukung pengukuran dan pembaruan ukurannya secara otomatis.

Saya merasa ini adalah sisi buruk yang cukup besar. Untuk hampir setiap kisi yang saya tulis, saya perlu memiliki 3 atau 4 kolom lebar tetap (untuk label status, beberapa meta data, ajakan bertindak, dll.) Dan 1 kolom lebar dinamis yang menempati sisa ruang yang tersedia.

Saya menghargai bahwa "tidak mendukung" tidak berarti ini tidak akan mungkin dilakukan dengan penambahan kode dan komponen tambahan seperti Autosizer - alangkah baiknya jika kasus penggunaan tersebut dipertimbangkan dengan baik dan solusi didokumentasikan untuk mereka yang membutuhkan kolom dinamis tetapi tidak ingin pergi ke bereaksi-virtual untuk semua bagasi yang dibawanya.

alangkah baiknya jika kasus penggunaan tersebut dipertimbangkan dengan baik dan solusi didokumentasikan untuk mereka yang membutuhkan kolom dinamis

Benar-benar dipahami - tetapi secara praktis, itu akan membutuhkan banyak usaha , dan perpustakaan ini telah menjadi karya cinta (bukan upaya yang dibayar). Sayangnya saya bahkan belum punya waktu untuk menyelesaikan upaya v2 terbatas saya, apalagi yang lebih agresif. 😞

alangkah baiknya jika kasus penggunaan tersebut dipertimbangkan dengan baik dan solusi didokumentasikan untuk mereka yang membutuhkan kolom dinamis

Benar-benar dipahami - tetapi secara praktis, itu akan membutuhkan banyak usaha , dan perpustakaan ini telah menjadi karya cinta (bukan upaya yang dibayar). Sayangnya saya bahkan belum punya waktu untuk menyelesaikan upaya _scoped down_ v2 saya, apalagi yang lebih agresif. 😞

Ya. Saya mengerti. Semoga upaya-upaya semacam itu bisa dipimpin oleh masyarakat.

Akan menyenangkan- tetapi menurut pengalaman saya, itu tidak pernah terjadi: senyum:

Saya tidak dapat menggunakan WindowScroller dengan DynamicSizedList, mungkin karena rendering tepat waktu membuat scrollTo tidak berfungsi dengan baik. Apakah ini mungkin dengan versi baru?

Saya telah menerima kenyataan bahwa saya tidak punya waktu atau tenaga untuk menyelesaikan upaya ini. Jika ada yang ingin turun tangan dan menyelesaikan cabang yang saya mulai, saya akan menyambut baik bantuan Anda. (Lihat juga edisi # 6 untuk detail tentang List dan Grid harus diterapkan untuk mendukung pengukuran just-in-time.)

Hai @bughsyourningsih ,
Saya telah membuat diskusi di garpu saya dengan beberapa catatan acak.
Beri tahu saya jika ada sesuatu yang seharusnya tidak ada dalam daftar atau tidak benar. Saya akan menyelesaikan daftarnya ketika saya akan membuat kemajuan.

Sepertinya barang bagus

Apakah halaman ini membantu?
0 / 5 - 0 peringkat