
Hiệu Suất React Native Và Cách Khắc Phục (Part 1)
Chào các bạn, chắc hẳn là 1 dev Mobile nói chung và dev React Native nói riêng thì vấn đề về hiệu năng là 1 vấn đề khá đau đầu và nó cũng hay xảy ra thường xuyên trong các dự án chúng ta đang làm. Hôm nay mình sẽ đi tổng quan về hiệu suất trong React Native và đây hứa hẹn sẽ là series về Perfomance giúp các bạn giải quyết các vấn đề về hiệu suất.
Nguyên nhân thực sự đằng sau các vấn đề về hiệu suất trong React Native
Hiệu suất của ứng dụng React Native có thể bị ảnh hưởng bởi nhiều nguyên nhân khác nhau, bao gồm:
- JavaScript Thread Blockage:
- React Native chạy mã JavaScript trên một luồng riêng biệt gọi là JavaScript thread. Nếu mã JavaScript thực hiện các tác vụ tốn thời gian như xử lý dữ liệu nặng hoặc tính toán phức tạp, nó có thể chặn luồng này và gây ra hiện tượng giật lag.
- Bridge Communication Overhead:
- React Native sử dụng một cầu nối (bridge) để giao tiếp giữa mã JavaScript và mã gốc (native). Nếu có nhiều yêu cầu truyền dữ liệu qua lại giữa JavaScript và mã gốc, nó có thể gây ra độ trễ và giảm hiệu suất.
- Inefficient Component Rendering:
- Sử dụng không hiệu quả các thành phần (components) hoặc không quản lý tốt vòng đời của chúng có thể dẫn đến việc render lại không cần thiết, gây tốn tài nguyên.
- Memory Leaks:
- Việc không giải phóng đúng cách các tài nguyên hoặc giữ lại các tham chiếu không cần thiết có thể dẫn đến rò rỉ bộ nhớ, làm giảm hiệu suất ứng dụng.
- Heavy Animations:
- Các hoạt ảnh phức tạp hoặc thực hiện quá nhiều hoạt ảnh cùng lúc có thể làm chậm ứng dụng nếu không được tối ưu hóa đúng cách.
- Unoptimized Images and Assets:
- Sử dụng hình ảnh và tài nguyên không được tối ưu hóa (kích thước lớn, định dạng không phù hợp) có thể tăng thời gian tải và tiêu tốn nhiều bộ nhớ hơn.
Các bước để tối ưu hóa ứng dụng React Native
Để tối ưu hóa hiệu suất ứng dụng React Native, bạn có thể thực hiện các bước sau:
1.Sử dụng PureComponent và memo:
Sử dụng React.PureComponent hoặc React.memo để tránh render lại không cần thiết cho các thành phần không thay đổi.
// Sử dụng PureComponent
class MyComponent extends React.PureComponent {
render() {
return ;
}
}
// Sử dụng memo
const MyFunctionalComponent = React.memo(({ data }) => {
return ;
});
2.Quản lý State Hiệu Quả:
Tránh đặt state trong các component quá cao trong cây component, và sử dụng các hooks như useState và useReducer một cách hiệu quả.
// Sử dụng hooks để quản lý state hiệu quả
const MyComponent = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return <button onClick={increment}>Increment</button>;
};
3.Tối ưu hóa các hàm render và callback:
Sử dụng useCallback và useMemo để nhớ lại các hàm và giá trị đã được tính toán trước đó nhằm tránh tính toán lại không cần thiết.
const MyComponent = ({ value }) => {
const expensiveCalculation = useMemo(() => computeExpensiveValue(value), [value]);
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
return <button onClick={handleClick}>Click me</button>;
};
4.Sử dụng FlatList và SectionList:
Đối với danh sách dữ liệu lớn, sử dụng FlatList hoặc SectionList thay vì ScrollView để tối ưu hóa việc render các item trong danh sách.
const MyComponent = ({ value }) => {
const expensiveCalculation = useMemo(() => computeExpensiveValue(value), [value]);
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
return <button onClick={handleClick}>Click me</button>;
};
5.Sử dụng Image và Assets Hiệu Quả:
Sử dụng các hình ảnh có kích thước phù hợp và định dạng tối ưu, và sử dụng react-native-fast-image để tải hình ảnh nhanh hơn và quản lý bộ nhớ tốt hơn.
// Sử dụng react-native-fast-image
import FastImage from 'react-native-fast-image';
const MyImage = () => {
return (
<FastImage
style={{ width: 200, height: 200 }}
source={{
uri: 'https://example.com/image.jpg',
priority: FastImage.priority.high,
}}
resizeMode={FastImage.resizeMode.contain}
/>
);
};
6.Tối ưu hóa Bridge Communication:
Giảm thiểu số lần giao tiếp qua bridge giữa JavaScript và mã gốc, và chỉ gửi dữ liệu cần thiết.
// Giảm thiểu số lần giao tiếp qua bridge
const fetchData = async () => {
const result = await NativeModules.ExampleModule.getBulkData();
// Xử lý dữ liệu tại đây
};
7.Sử dụng Animations một cách Thận Trọng:
Sử dụng thư viện react-native-reanimated hoặc lottie-react-native để thực hiện các hoạt ảnh mượt mà và tối ưu.
// Sử dụng react-native-reanimated
import Animated from 'react-native-reanimated';
const MyAnimation = () => {
const value = new Animated.Value(0);
Animated.timing(value, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}).start();
return <Animated.View style={{ opacity: value }} />;
};
8.Giải phóng Bộ nhớ:
Đảm bảo rằng tất cả các tài nguyên không cần thiết được giải phóng và tránh rò rỉ bộ nhớ bằng cách sử dụng hooks như useEffect để dọn dẹp các tài nguyên khi component bị hủy.
// Dọn dẹp tài nguyên trong useEffect
useEffect(() => {
const interval = setInterval(() => {
// Fetch data
}, 1000);
return () => clearInterval(interval); // Dọn dẹp khi component bị hủy
}, []);
9.Đo Lường và Phân Tích Hiệu Suất:
Sử dụng các công cụ như React Native Performance Monitor, Flipper, và các thư viện profiling để đo lường và phân tích hiệu suất của ứng dụng, từ đó tìm ra và giải quyết các vấn đề cụ thể.
// Sử dụng React Native Performance Monitor và Flipper
import { Performance } from 'react-native-performance';
const measurePerformance = () => {
const mark = Performance.mark('start');
// Thực hiện một số tác vụ
Performance.measure('start', 'end', mark);
};
10.Tối ưu hóa Khởi Động Ứng Dụng:
Giảm thiểu số lượng thư viện và module được tải khi khởi động ứng dụng, và sử dụng kỹ thuật như lazy loading để chỉ tải các phần cần thiết khi cần.
// Sử dụng lazy loading
const LazyComponent = React.lazy(() => import('./LazyComponent'));
const MyApp = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
};
Thực hiện các bước trên sẽ giúp bạn tối ưu hóa hiệu suất của ứng dụng React Native, mang lại trải nghiệm mượt mà và nhanh chóng cho người dùng.







-
Tagged flutter, mobile-dev, react-native