Theo thống kê từ Google có khoảng 53% người dùng sẽ rời khỏi ứng dụng di động nếu mất hơn 3 giây để tải. Điều này có nghĩa là với mỗi giây ứng dụng của bạn tải thất bại thì bạn sẽ mất đi một lượng khách hàng tiềm năng. Trong bài viết này, chúng ta sẽ thảo luận về các phương pháp để tối ưu hiệu suất hoạt động của ứng dụng di động được viết bằng React Native.
1. Sử dụng shouldComponentUpdate hoặc PureComponent
Đối với các component thông thường, trong một vài trường hợp chúng ta không muốn bị render lại thì việc sử dụng phương thức shouldComponentUpdate sẽ là một giải pháp hiệu quả giúp bạn xử lý vấn đề này bằng cách cho giá trị trả về của phương thức này bằng false sẽ ngăn component render lại.
PureComponent hoàn toàn tương tự với Component thông thường ngoài trừ việc nó sẽ xử lý shouldComponentUpdate giúp bạn.
1 | class MyComponent extends React.Component { |
2. Sử dụng thuộc tính key cho mỗi mục trong danh sách được render
Danh sách là thứ được sử dụng thường xuyên nhất trong mọi ứng dụng. Nếu bạn không đặt thuộc tính key cho mỗi mục trong danh sách thì React sẽ render lại toàn bộ các mục trong danh sách khi có bất kỳ một mục nào được thêm vào hoặc xoá ra khỏi danh sách. Khi có thuộc tính key thì react sẽ hạn chế render lại toàn bộ danh sách mà chỉ render lại những mục thay đổi.
1 | class MyComponent extends React.PureComponent { |
3. Thực hiện bind trong constructor và không tạo hàm trong render
Làm điều này:
1 | class MyComponent extends React.PureComponent { |
Đừng làm điều này trong render:
1 | <Text onPress={ () => this.doWork() }>Do Some Work</Text> |
hoặc
1 | <Text onPress={ this.doWork.bind(this) }>Do Some Work</Text> |
Bởi vì như vậy hàm render sẽ được gọi rất thường xuyên và mỗi lần bạn viết như 2 cách trên thì một hàm mới sẽ được tạo ra.
Nếu bạn muốn truyền tham số vào hàm doWork, bạn có thể cần phải tạo một component con và truyền hàm vào như một prop.
1 | <child arg1={arg1}></child> |
Và trong component con sẽ viết như sau:
1 | doWork() { |
Nếu bạn đang tạo một component ở trên cùng thì cần phải đánh đổi một ít hiệu suất nhưng code sẽ dễ đọc hơn bằng cách sử dụng closure như bên dưới. Một hàm mới sẽ được tạo ra mỗi khi render lại.
1 | doWork = (param) => () => { |
Vì vậy bạn cần cân nhắc giữa khả năng đọc code và yêu cầu hiệu suất trong những trường hợp như vậy.
4. Đừng cập nhật state hoặc dispatch actions trong componentWillUpdate
Phương thức componentWillUpdate được sử dụng để chuẩn bị cho một sự thay đổi, không dùng để kích hoạt một đối tượng khác. Nếu bạn muốn setState hoặc dispatch bất kỳ redux actions nào hãy thực hiện nó trong componentWillReceiveProps.
5. Sử dụng VirtualizedList, FlatList và SectionList cho một tập dữ liệu lớn
Theo tài liệu từ React Native thì VirtualizedList, FlatList và SectionList cho hiệu suất cao hơn khi render list. Nếu bạn có một danh sách với hàng trăm dòng thì các dòng đó sẽ chỉ được hiển thị trên màn hình khi bạn cuộn xuống.
VirtualizedList dựa trên cả FlatList và SectionList nên nếu bạn có một tập dữ liệu bất biến thì bạn nên sử dụng trực tiếp VirtualizedList.
6. Sử dụng Perf monitor để theo dõi FPS
Hãy vào developer tool và mở perf monitor lên. Bây giờ khi bạn bắt đầu tương tác, điều hướng hoặc cuộn lên/xuống ứng dụng của bạn, bạn có thể nhìn thấy FPT bị suy giảm. Chủ yếu sự suy giảm này đến từ JS Thread chứ không từ native UI Thread. Vì vậy ta có thể tìm các điểm chết nơi FPT bị giảm, bạn có thể đã setState hoặc dispatch redux actions sai ở một vài chỗ hoặc thực hiện qúa nhiều công việc bất đồng bộ trên JS Thread.