Tự học ReactJS: React Performance – Sử dụng react-virtual

Vấn đề là gì?

Như chúng ta biết thì React rất tối ưu khi update DOM, nhưng trong một số trường hợp chúng ta render một list quá nhiều phần tử có khi lên đến hàng ngàn item sẽ ảnh hưởng đến performance. Bạn hãy tưởng tượng như khi bạn loop qua một list gồm hàng ngàn item và sort list đó. Điều này sẽ làm chậm quá trình render rất nhiều, đặc biệt là trên các thiết bị động.

Thực sự chúng ta không cần render quá nhiều item cho một list. Nếu list đó gồm 10,000 items, chúng ta sẽ chia nhỏ nó ra. Chúng ta chỉ nên hiện thị vừa đủ item lên màn hình cho người dùng. Vì thực chất trên một screen (hay một section) chúng ta chỉ hiển thị một số item nhất định, ví dụ có thể là 10-20-100 items. Tại sao phải render quá nhiều trong khi người dùng ko nhìn thấy?

Ví dụ như screen sau đây:

Chúng ta chỉ hiển thị 15 items cho danh sách như trên (thực tế danh sách này gồm 100,000 phần tử). Nó hoạt động như sau, khi bạn scroll xuống trong danh sách trên thì react-virtual sẽ tự động load thêm item cần thiết, tương tự kỹ thuật lazy-loading hay on-demand loading. Khi scroll tới đâu thì load thêm item tới đó. Điều này sẽ giúp React render nhanh hơn vì có ít item hơn.

Sử dụng react-virtual

Ví dụ sử dụng react-virtual cho một list gồm nhiều phần tử như sau:

// before
function MyListOfData({items}) {
  return (
    <ul style={{height: 300}}>
      {items.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  )
}
// after
function MyListOfData({items}) {
  const listRef = React.useRef()
  const rowVirtualizer = useVirtual({
    size: items.length,
    parentRef: listRef,
    estimateSize: React.useCallback(() => 20, []),
    overscan: 10,
  })

  return (
    <ul ref={listRef} style={{position: 'relative', height: 300}}>
      <li style={{height: rowVirtualizer.totalSize}} />
      {rowVirtualizer.virtualItems.map(({index, size, start}) => {
        const item = items[index]
        return (
          <li
            key={item.id}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: size,
              transform: `translateY(${start}px)`,
            }}
          >
            {item.name}
          </li>
        )
      })}
    </ul>
  )
}

Các bạn có thể tham khảo thêm nhiều ví dụ ở trang của react-virtual.

Nguồn: Epic React by Kent C.Dodds

Leave a Reply

Your email address will not be published. Required fields are marked *