Гүйцэтгэлийн оновчлол
Апп удаан ажиллах, дэлгэц чичрэх, scroll хийхэд хоцрох — эдгээр нь хэрэглэгчийг зайлуулдаг хамгийн муу туршлага. React Native дээр гүйцэтгэлийн асуудлууд ихэвчлэн re-render хэт олон удаа болж байгаагаас үүсдэг. Цөөн өөрчлөлтөөр аппыг мэдэгдэхүйц хурдасгаж болно — яаж болохыг сурцгаая.
Re-render-г тань тодорхойлох
React дэх хамгийн түгээмэл гүйцэтгэлийн алдаа бол шаардлагагүй re-render. memo, useMemo, useCallback гурвыг зөв хэрэглэх нь асуудлыг ихэнхдээ шийдэж өгдөг.
React.memo нь component-н props өөрчлөгдөөгүй бол re-render хийхгүй:
import React, { memo, useState, useCallback } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
// memo ашиглахгүй бол parent re-render болох бүрт энэ ч render болно
const CourseCard = memo(function CourseCard({
title,
onPress,
}: {
title: string;
onPress: () => void;
}) {
console.log('CourseCard render:', title); // Хэдэн удаа render болж байгааг ажиглана
return (
<TouchableOpacity style={styles.card} onPress={onPress}>
<Text style={styles.title}>{title}</Text>
</TouchableOpacity>
);
});
export default function CourseList() {
const [count, setCount] = useState(0);
// useCallback ашиглахгүй бол render бүрт шинэ функц үүснэ
// → memo ажиллахгүй болно
const handlePress = useCallback(() => {
console.log('Курс сонгогдлоо');
}, []); // dependency хоосон = функц хэзээ ч өөрчлөгдөхгүй
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => setCount(c => c + 1)}>
<Text style={styles.counter}>Тоолуур: {count} (дарахад CourseCard re-render болохгүй)</Text>
</TouchableOpacity>
<CourseCard title="JavaScript үндэс" onPress={handlePress} />
<CourseCard title="React Native" onPress={handlePress} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16, backgroundColor: '#0b1120' },
card: { backgroundColor: '#0f172a', padding: 16, borderRadius: 12, marginBottom: 8 },
title: { color: '#f1f5f9', fontSize: 16 },
counter: { color: '#94a3b8', marginBottom: 16, fontSize: 14 },
});
useMemo нь тооцооллын үр дүнг cache хийнэ — нарийн шүүлтүүр, эрэмбэлэлт зэрэгт хэрэгтэй:
import { useMemo, useState } from 'react';
const lessons = [
{ id: 1, title: 'React Native гэж юу вэ?', completed: true },
{ id: 2, title: 'Node.js суулгах', completed: true },
{ id: 3, title: 'Expo тохируулга', completed: false },
{ id: 4, title: 'Анхны апп', completed: false },
];
export default function LessonList() {
const [showCompleted, setShowCompleted] = useState(true);
// showCompleted өөрчлөгдөхөд л дахин шүүнэ, бусад render-д cache ашиглана
const filtered = useMemo(
() => lessons.filter(l => showCompleted || !l.completed),
[showCompleted]
);
return (
// ...filtered-г харуулах UI
);
}
FlatList оновчлол
FlatList нь том жагсаалтад зориулагдсан боловч буруу ашиглавал удаашрал үүснэ. Доорх props-үүд гүйцэтгэлд мэдэгдэхүйц нөлөөтэй:
import { FlatList, View, Text, StyleSheet } from 'react-native';
import { memo, useCallback } from 'react';
type Lesson = { id: string; title: string; order: number };
// Item component-г memo-оор бүтээх нь чухал
const LessonItem = memo(({ item }: { item: Lesson }) => (
<View style={styles.item}>
<Text style={styles.order}>{item.order}</Text>
<Text style={styles.title}>{item.title}</Text>
</View>
));
export default function OptimizedList({ lessons }: { lessons: Lesson[] }) {
// keyExtractor render бүрт шинэ функц болохоос сэргийлнэ
const keyExtractor = useCallback((item: Lesson) => item.id, []);
// renderItem render бүрт шинэ функц болохоос сэргийлнэ
const renderItem = useCallback(
({ item }: { item: Lesson }) => <LessonItem item={item} />,
[]
);
return (
<FlatList
data={lessons}
keyExtractor={keyExtractor}
renderItem={renderItem}
// Дэлгэцнээс гадна хэдэн item урьдчилан render хийхийг тохируулна
windowSize={5}
// Эхний render-д хэдэн item харуулах
initialNumToRender={10}
// Scroll хийхэд хэдэн item нэмж render хийх
maxToRenderPerBatch={5}
// Item өндрийг мэдэж байвал getItemLayout ашиглах нь маш хурдан
getItemLayout={(_, index) => ({
length: 60,
offset: 60 * index,
index,
})}
removeClippedSubviews={true}
/>
);
}
const styles = StyleSheet.create({
item: { flexDirection: 'row', padding: 16, borderBottomWidth: 1, borderBottomColor: '#1e293b', height: 60, alignItems: 'center' },
order: { color: '#475569', width: 32, fontSize: 14 },
title: { color: '#f1f5f9', flex: 1, fontSize: 15 },
});
Зураг болон сүлжээний оновчлол
Зурган файлууд нь аппын хамгийн их санах ой зарцуулдаг хэсэг. Хэдэн арга хэмжээ авснаар мэдэгдэхүйц сайжирна:
import { Image, View, StyleSheet } from 'react-native';
// Муу: том хэмжээтэй зургийг жижиг контейнерт харуулна
function BadExample() {
return (
<Image
source={{ uri: 'https://example.com/huge-4k-image.jpg' }}
style={{ width: 80, height: 80 }}
/>
);
}
// Сайн: зөв хэмжээний зураг + cache тохируулга
function GoodExample() {
return (
<Image
source={{ uri: 'https://example.com/thumbnail-80x80.jpg' }}
style={styles.avatar}
// Зургийг дахин татахгүйн тулд cache хийнэ
defaultSource={require('./assets/placeholder.png')}
fadeDuration={200}
resizeMode="cover"
/>
);
}
// Expo Image нь илүү хурдан, cache дэмжсэн сонголт
import { Image as ExpoImage } from 'expo-image';
function BestExample() {
return (
<ExpoImage
source="https://example.com/image.jpg"
style={styles.avatar}
placeholder={{ blurhash: 'L6PZfSi_.AyE_3t7t7R**0o#DgR4' }}
contentFit="cover"
transition={200}
/>
);
}
const styles = StyleSheet.create({
avatar: { width: 80, height: 80, borderRadius: 40 },
});
Гүйцэтгэлийн оновчлол нь нэг удаа хийгдэх зүйл биш — апп өсөх тусам байнга анхаарах хэрэгтэй. Харин энд сурсан суурь аргуудыг эхнээс нь мөрдвөл том асуудал гарахгүй.
Дараагийн хичээлд:
Hermes engine — Expo болон React Native-д суурилагдсан JavaScript engine-г тохируулах, ашиглах, дибаг хийх талаар сурна. Hermes нь аппын эхлэх хурдыг мэдэгдэхүйц нэмэгдүүлдэг.