TABLE OF CONTENTS

Hi 🤓 Cảm ơn bạn đã ghé thăm blog này, nếu những bài viết trên blog giúp ích cho bạn. Bạn có thể giúp blog hiển thị quảng cáo bằng cách tạm ngừng ad blocker 😫 và để giúp blog duy trì hoạt động nếu bạn muốn.
Cảm ơn bạn!

React.memo()

Trong một số trường hợp, component của chúng ta re-render, ngay cả khi component này có props không thay đổi. Có rất nhiều nguyên nhân dẫn đến một component re-render. Một tình huống khá phổ biến đó là khi parent component thay đổi state kéo theo các child component re-render.

Để cải thiện performance cho website sử dụng React, chúng ta có thể cải thiện bằng cách hạn chế các re-render không cần thiết. Để làm điều đó thì React giới thiệu một feature là React.memo().

React.memo() sẽ giúp chúng ta hạn chế các re-render bằng cách kiểm tra xem props của component có thay đổi hay không.

Khi một component được wrap bởi React.memo(), React sẽ ghi nhớ(memoizes) kết quả của lần render này, và trước lần render tiếp theo, nếu new props không thay đổi so với lần ghi nhớ trước, React sẽ reuse kết quả nó đã ghi nhớ và bỏ qua lần render này.

Để hiểu rõ hơn React.memo() chúng ta cùng xem một ví dụ:

Ở ví dụ trên, khi click vào button update state, state của parent thay đổi dẫn đến các child component re-render. Như các bạn thấy, component <Post /> có props không thay đổi, nhưng khi parent update state thì <Post /> sẽ bị re-render và trong trường hợp này không có gì thay đổi trong component <Post />, nên việc re-render component này là không cần thiết ^^.

function App() {
  // Thay đổi state sẽ re-render child component
  const [count, setcount] = useState(0);

  return (
    <>
      <div>
        <b>Update state App </b>
        <button onClick={() => setcount(count + 1)}>
          UPDATE STATE ({count})
        </button>
      </div>
      <Post title="Tìm hiểu React.memo()" author="Nguyen Anh Vu" />
    </>
  );
}

function Post({ title, author }) {
  console.log("Không sử dụng React.memo");
  return (
    <div>
      <div>Bài viết: {title}</div>
      <div>Tác giả: {author}</div>
    </div>
  );
}

Khi sử dụng React.memo() ta sẽ hạn chế được re-render không cần thiết cho <Post />.

Để sử dụng React.memo() cho một component. Ta cần truyền một function component vào React.memo().

const MemoizedComponent = React.memo(function MyComponent(props) {
    // re-render nếu props thay đổi
});

Ở ví dụ trên thì ta sẽ wrap component <Post /> như sau:

const PostUseMemo = React.memo(function ({ title, author }) {
  console.log("Sử dụng React.memo");
  return (
    <div>
      <div>Bài viết: {title}</div>
      <div>Tác giả: {author}</div>
    </div>
  );
});

Các bạn có thể xem ở phần Console trong codesandbox, component sử dụng memo sẽ không re-render lại vì props title, author không thay đổi sau mỗi lần update state của parent component.

Các bạn có thể compare props bằng cách truyền một function vào đối số thứ 2 của memo.

function MyComponent(props) {
  /* render using props */
}
function areEqual(prevProps, nextProps) {
  /* return true khi các giá trị trong prevProps và nextProps bằng nhau. */

}
export default React.memo(MyComponent, areEqual);

Để kiểm tra props có thay đổi hay không, React sử dụng shallow compare để so sánh prevPropsnextProps. Mình đã có một bài viết về shallow compare, các bạn có thể đọc tại đây: Shallow Compare trong React là gì?.

Để kiểm tra props ở ví dụ trên, ta có thể triển khai như sau:

function areEqual(prevProps, nextProps) {
  return prevProps.title === nextProps.title
    && prevProps.author === nextProps.author;
  // return true => không re-render
}

Nếu trong trường hợp <Post /> có sử dụng các useState, useReducer hay useContext thì việc sử dụng React.memo sẽ không ngăn component này re-render. Đây là một lưu ý các bạn cần nắm ^^.

Có thể bạn thích ⚡
homiedev
About Me

Hi, I'm @devnav. Một người thích chia sẻ kiến thức, đặc biệt là về Frontend 🚀. Trang web này được tạo ra nhằm giúp các bạn học Frontend hiệu quả hơn 🎉😄.

Chúc các bạn tìm được kiến thức hữu ích trong blog này 😁😁.