Hiệu suất tối ưu hóa của memo và PureComponent trong React: Sự khác biệt khi xử lý component hàm và lớp
Trong React, để tối ưu hiệu suất, chúng ta thường sử dụng các phương pháp như `memo` cho component hàm và `PureComponent` cho component lớp. Mỗi phương pháp có cách hoạt động khác nhau và phù hợp với từng loại component.
1. Cơ chế render của React
Khi một component nhận được props hoặc state thay đổi, React sẽ render lại component đó. Tuy nhiên, nếu props không thay đổi, việc render lại này là không cần thiết và gây tốn kém hiệu suất.
2. memo cho component hàm
`memo` là mộtHigher-Order Component (HOC) giúp cache kết quả render của component hàm. Nó chỉ render lại khi props thay đổi.
Ví dụ:
import React, { memo } from 'react';
const MyComponent = memo((props) => {
console.log('MyComponent is rendering');
return (
<div>
<p>{props.thongBao}</p>
</div>
);
});
export default MyComponent;
Trong trường hợpprops là một đối tượng:
import React, { memo } from 'react';
const MyComponent = memo((props) => {
return (
<div>
<p>{props.duLieu.ten}</p>
</div>
);
});
const ParentComponent = () => {
const duLieu = { ten: 'John' };
return (
<div>
<MyComponent duLieu={duLieu} />
{() => {
const moiDuLieu = duLieu;
return <MyComponent duLieu={moiDuLieu} />;
}}
</div>
);
};
Nếu thay đổi props bằng cách tạo một đối tượng mới:
const moiDuLieu = { ten: 'John' };
`memo` sẽ nhận diện props thay đổi và render lại component.
Bạn cũng có thể định nghĩa một hàm so sánh tùy chỉnh:
import React, { memo } from 'react';
const soSanh = (prevProps, nextProps) => {
return prevProps.someProp === nextProps.someProp;
};
const MyComponent = memo((props) => {
return (
<div>
<p>{props.tinNhan}</p>
</div>
);
}, soSanh);
export default MyComponent;
3. PureComponent cho component lớp
`PureComponent` là một lớp cơ sở trong React. Khi thừa kế từ `PureComponent`, React sẽ tự động so sánh nông (shallow compare) props và state để quyết định có render lại không.
Ví dụ:
import React, { PureComponent } from 'react';
class MyComponent extends PureComponent {
render() {
console.log('MyComponent is rendering');
return (
<div>
<p>{this.props.thongBao}</p>
</div>
);
}
}
export default MyComponent;
Ưu điểm:
- Tự động so sánh nông props và state
- Giảm số lần render không cần thiết
Giới hạn:
- Không nhận diện thay đổi trong các đối tượng hoặc mảng嵌套
- Không thể thay đổi logic so sánh
4. So sánh giữa memo và PureComponent
| Feature | memo | PureComponent |
|---|---|---|
| Loại component | Component hàm | Component lớp |
| So sánh nông | Có | Có |
| Tùy chỉnh logic so sánh | Có | Không |
| Cách sử dụng | Bọc component | Thừa kế |
5. Lựa chọn tối ưu hóa phù hợp
Đối với component hàm:
- Sử dụng `memo` để giảm render không cần thiết
- Định nghĩa hàm so sánh tùy chỉnh nếu cần
Đối với component lớp:
- Sử dụng `PureComponent` để so sánh nông props và state
- Thực hiện các cập nhật state một cách bất biến để đảm bảo hiệu quả
Ví dụ với `PureComponent` và state bất biến:
import React, { PureComponent } from 'react';
import produce from 'immer';
class MyComponent extends PureComponent {
constructor(props) {
super(props);
this.state = {
duLieu: { ten: 'John' }
};
}
handleClick = () => {
this.setState(
produce((draft) => {
draft.duLieu.ten = 'Jane';
})
);
};
render() {
return (
<div>
<button onClick={this.handleClick}>Cập nhật</button>
<p>{this.state.duLieu.ten}</p>
</div>
);
}
}
export default MyComponent;
Trong trường hợp phức tạp, có thể kết hợp các phương pháp như `memo`, `PureComponent`, `useCallback`, `useMemo` để đạt hiệu quả tối ưu.