Q5. Các vấn đề thường gặp về performance trong React Native?
Re-render không cần thiết
Vấn đề:
Re-render không cần thiết có thể làm giảm performance của ứng dụng trong quá trình re-rendering tốn nhiều tài nguyên, đặc biệt khi cây component trở nên phức tạp
Giải pháp:
PureComponent và memo: Sử dụng React.PureComponent hoặc React.memo để tránh re-render không cần thiết
useCallback và useMemo: Sử dụng useCallback và useMemo để tối ưu hoá các hàm callback và giá trị được tính toán
import React, { memo, useCallback, useState } from 'react';
import { Text, Button, View } from 'react-native';
const ExpensiveComponent = memo(({ onPress }) => {
return <Button title="Press me" onPress={onPress} />;
});
const MyComponent = () => {
const [count, setCount] = useState(0);
const handlePress = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<View>
<Text>Count: {count}</Text>
<ExpensiveComponent onPress={handlePress} />
</View>
);
};
Memory leaks
Vấn đề:
Memory leaks xảy ra khi các đối tượng không được giải phóng bộ nhớ sau khi không còn cần thiết, dẫn đến tăng dần lượng bộ nhớ sử dụng
Giải pháp:
Cleanup trong useEffect: Đảm bảo cleanup đúng cách trong useEffect bằng cách trả về một hàm cleanup
Unmount Listeners: Huỷ bỏ các listeners và subscriptions khi component unmount
import React, { useEffect } from 'react';
import { View } from 'react-native';
const MyComponent = () => {
useEffect(() => {
const intervalId = setInterval(() => {
// some logic
}, 1000);
return () => clearInterval(intervalId); // cleanup
}, []);
return <View />;
};
Quản lý danh sách lớn
Vấn đề:
Hiển thị và quản lý danh sách lớn có thể dẫn đến hiệu suất kém, đặc biệt khi tất cả các item được render cùng lúc
Giải pháp:
FlatList và SectionList: Sử dụng FlatList và SectionList thay vì ScrollView để tối ưu hoá render danh sách lớn
Virtualized List: Đảm bảo rằng chỉ những phần tử đàng nhìn thấy mới được render
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const MyComponent = () => {
const data = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
keyExtractor={(item, index) => index.toString()}
/>
);
};
Hình ảnh lớn
Vấn đề:
Sử dụng hình ảnh lớn không được tối ưu hoá có thể làm giảm hiệu suất ứng dụng
Giải pháp:
Resize và nén hình ảnh: Tối ưu hoá kích thước và nén hình ảnh trước khi sử dụng
react-native-fast-image: Sử dụng thư viện như react-native-fast-image để cải thiện hiệu suất tải và hiển thị hình ảnh
import FastImage from 'react-native-fast-image'; const MyComponent = () => { return ( <FastImage style={{ width: 200, height: 200 }} source={{ uri: 'https://example.com/image.png', priority: FastImage.priority.high, }} resizeMode={FastImage.resizeMode.contain} /> ); };
Xử lý animation
Vấn đề:
Animations có thể gây giảm hiệu suất nếu không được tối ưu hoá đúng cách
Giải pháp:
useNativeDriver: Sử dụng useNativeDriver cho các animations để tận dụng tối đa hiệu suất của native thread
Reanimated và Lottie: Sử dụng thư viện như react-native-reanimated hoặc lottie-react-native cho các animation phức tạp và hiệu quả
import React, { useRef, useEffect } from 'react'; import { Animated } from 'react-native'; const MyComponent = () => { const fadeAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(fadeAnim, { toValue: 1, duration: 1000, useNativeDriver: true, }).start(); }, [fadeAnim]); return <Animated.View style={{ opacity: fadeAnim }} />; };
6. Khởi động ứng dụng chậm
Vấn đề:
Ứng dụng có thời gian khởi động chậm có thể gây trải nghiệm người dùng không tốt.
Giải pháp:
Code splitting và lazy loading: Sử dụng kỹ thuật phân tách mã và lazy loading để tải các phần của ứng dụng khi cần thiết.
Optimize bundle size: Tối ưu hóa kích thước bundle bằng cách loại bỏ các mã không cần thiết và sử dụng các thư viện nhẹ hơn.
7. Background Tasks
Vấn đề:
Xử lý các tác vụ nền có thể gây chậm hiệu suất nếu không được quản lý đúng cách.
Giải pháp:
react-native-background-fetch: Sử dụng thư viện như
react-native-background-fetch
để quản lý các tác vụ nền.Headless JS: Sử dụng Headless JS để thực hiện các tác vụ nền khi ứng dụng không hoạt động.
jsxCopy codeimport BackgroundFetch from "react-native-background-fetch";
BackgroundFetch.configure({
minimumFetchInterval: 15,
stopOnTerminate: false,
startOnBoot: true,
}, async (taskId) => {
// Perform background task
console.log("[BackgroundFetch] taskId: ", taskId);
BackgroundFetch.finish(taskId);
}, (taskId) => {
console.log("[BackgroundFetch] TIMEOUT taskId: ", taskId);
BackgroundFetch.finish(taskId);
});