What is React.memo and How to use it?

Hello, bài viết hôm nay mình sẽ giới thiệu đến mọi người một khái niệm của React được giới thiệu trong phiên bản 16.6 đó chính là React.memo.
enter image description here
Bài viết gốc tại: https://www.juliandong.com/2020/03/what-is-reactmemo-and-how-to-use-it.html

1. Giới thiệu về React.memo

Trong React, với 1 class component ta có thể bỏ qua việc render lại component khi props được truyền vào giống nhau bằng cách chuyển nó thành PureComponent hoặc dùng hàm shouldComponentUpdate(). Vậy nếu component của bạn ở dạng function component thì như thế nào?
Khi đó chúng ta cần tới React.memo. Đây là một High Order Component tương tự như PureComponent nhưng dùng cho function component.

const MyMemo = React.memo(function MyComponent(){
    // only render when props change
})

2. Cách thức hoạt động

Khi quyết định cập nhật DOM, React đầu tiên sẽ render component, tiếp đó, với mỗi lần render, React sẽ so sánh kết quả render giữa các lần với nhau, nếu các kết quả đó khác nhau thì DOM mới được cập nhật.

React.memo

Nếu component render cùng 1 kết quả khi truyền cùng 1 props, thì ta có thể wrap nó trong React.memo để làm tăng hiệu suất bằng cách ghi nhớ kết quả render. Cụ thể như sau: Khi function component được wrap trong React.memo thì kết quả render sẽ được nhớ (memoize). Trước lần render tiếp theo, vì props không đổi nên kết quả không thay đổi, nên thay vì render lần nữa thì thì React sẽ dùng lại kết quả đã được nhớ lúc đầu.

Chúng ta có thể tham khảo ví dụ sau:

export function Movie({title, date}) {
    return (
        <div>
            <h1>{title}</h1>
            <span>{date}</span>
        </div>
    )
}

export const MemoizedMovie = React.memo(Movie)

React.memo(Movie) trả về một memoized component tên là MemoizedMovie. Component này giống hệt Movie ngoại trừ 1 điều là: Kết quả render của MemoizedMovie được nhớ. Kết quả nhớ này sẽ được dùng lại miễn là props title và date được giữ nguyên ở lần render tiếp theo. Điều này sẽ cải thiện được hiệu suất vì khi tái sử dụng nội dung được nhớ (memoized content), React sẽ bỏ qua được việc re-render component và đồng thời không thực hiện việc difference check đối với DOM

// First render. React calls MemoizedMovie function.
<MemoizedMovie 
  title="Heat"
  releaseDate="December 15, 1995" 
 />
// On next round, React used memoized content instead of calling MemoizedMovie,prevent re-rendering
<MemoizedMovie 
  title="Heat"
  releaseDate="December 15, 1995" 
 /> // Same props

Customize props check

Mặc định, React.memo chỉ shallow compare props và object của props. Chúng ta có thể dùng 1 tham số thứ 2 để tùy biến hàm equality check:

React.memo(Component, areEqual(prevProps, nextProps))

Ví dụ, ta tạo thêm 1 memoized Component là MemoizedMovie2 như sau:

const areEqual = (prevProps, nextProps) => prevProps.title === nextProps.title && prevProps.date === nextProps.date;

const MemoizedMovie2 = React.memo(Movie, areEqual)

3. Khi nào nên sử dụng React.memo

Một trong những trường hợp tốt nhất để dùng React.memo đó là khi chúng ta mong muốn function component render thường xuyên với cùng props. Một ví dụ điển hình là function component bị bắt buộc render bởi component cha.

Hãy xét ví dụ dưới đây:
Ta sẽ dùng lại component Movie đã tạo ở trên, và tạo thêm 1 component MovieViewsRealtime để cập nhật realtime số lượt view của từng bộ phim

function MovieViewsRealtime({title, date, views}) {
    return (
        <div>
            <Movie title={title} date={date} />
            <span>Views: {views} </span>
        </div>
    )
}

Khi chạy, ứng dụng sẽ poll lên server mối giây để lấy thông tin về lượt views của phim

// Initial render (0s), views = 0
<MovieViewsRealtime
    title="No time to die"
    date="01/04/2020"
    views={0}
/>

// After 1s, views = 10
<MovieViewsRealtime
    title="No time to die"
    date="01/04/2020"
    views={10}
/>

// After 2s, views = 20
<MovieViewsRealtime
    title="No time to die"
    date="01/04/2020"
    views={20}
/>
// and so on

Mỗi lần props views thay đổi thì MovieViewsRealtime sẽ được re-render, kéo theo Movie sẽ re-render mặc dù title và date không thay đổi. Lúc này, ta cần áp dụng React.memo cho Movie component.

Chúng ta sửa MovieViewsRealtime để sử dụng MemoizedMovie

function MovieViewsRealtime({title, date, views}) {
    return (
        <div>
            <MemoizedMovie title={title} date={date} />
            <span>Views: {views} </span>
        </div>
    )
}

Lúc này, chỉ cần title và date không thay đổi, React sẽ bỏ qua việc render MemoizeMovie, nhờ đó cải thiện được performance cho MovieViewsRealtime.

Kết

React.memo là công cụ tuyệt vời để memoized cho function component. Nếu áp dụng chính xác, performance có thể được cải thiện vì sẽ tránh được việc re-render nếu nextProps và prevProps không thay đổi. Chúng ta có thể sử dụng profiling để đo lường performance của việc dùng React.memo.

Bạn có biết những use case nào khác sử dụng **React.memo* không? Nếu có hãy comment ở dưới đây nhé. Thanks!*

Reference

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Julian Dong

5 bài viết.
18 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
24 6
Giới thiệu chung Devdocs là một tài liệu rất hữu ích cho lập trình viên dùng để tra cứu các API của các ngôn ngữ lập trình hay các framework cũng ...
Julian Dong viết hơn 4 năm trước
24 6
White
3 3
Xin chào mọi người, bài viết hôm nay sẽ liên quan đến một công cụ quản lý source code vô cùng quen thuộc đối với developer hiện nay đó chính là Git...
Julian Dong viết 4 tháng trước
3 3
White
2 0
Hôm nay gặp một bug này thấy rất hay nên muốn ghi lại và chia sẻ cho mọi người Số là mình làm app 1 form đăng nhập bằng email và password. Ban đầu...
Julian Dong viết hơn 1 năm trước
2 0
Bài viết liên quan
White
0 0
Performance regression in ActiveRecord model instance creation in Rails 4.1.x When you guys met the performance issue in Rails 4.1.x. And after be...
Luu Nguyen viết gần 4 năm trước
0 0
White
17 3
(Link) (Link) &mdash; tracks device battery state. (Link) (Link) &mdash; tracks geo location state of user's device. (Link) (Link) &mdash; tr...
Đinh Viễn viết 11 tháng trước
17 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
5 bài viết.
18 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!