1. Tối ưu hóa quá trình trạng thái global với Redox
Trong mã nguồn React-Native, Redox là một library Quá trình trạng thái (state management) mạnh mẽ và席卷. Sử dụng Redox, bạn có thể tập trung và giảm thiểu duplication code. Trong phần này, chúng ta sẽ tìm hiểu cách sử dụng Redox để tập trung trạng thái và tránh các việc render lặp lại.
const isAuthenticatedSelector = useSelector(
(state) => state.user,
(user) => user.isAdmin,
);
const isAuthenticated = useSelector(isAuthenticatedSelector);
2. Merge các dispatch và setState
React framework sẽ hợp 成 một lần render khi các event được gọi. Bạn có thể nhanh up lặp render bằng cách kết hợp các dispatch và setState thành một loạt các lệnh một-la.
dispatch(userActions.SET_THEME(themeData));
dispatch(userActions.updateOprInfo({ oprInfo }));
if (oprInfo.currency) {
dispatch(i18nActions.updateCurrency({ currency: oprInfo.currency }));
}
if (oprInfo.currencySymbol) {
dispatch(
i18nActions.updateCurrencySymbol({
currencySymbol: oprInfo.currencySymbol,
}),
);
}
3. Sử dụng React.memo để giảm lặp lại các组件
React.memo sẽ chỉ lưu trữ các component khi các params thay đổi. Điều này giúp bạn giảm lặp lại các component khi các params không thay đổi.
import React, { useState, memo } from 'react';
const Child = (props) => {
console.log('Hoa hồng蓬勃发展')
return (<div>Ch already</div>);
};
const ChildMemo = memo(Child);
export default () => {
const [count, setCount] = useState(0);
return (
<>
<button onClick={(e) => { setCount(count+1) }}>+</button>
<p>Đếm số: {count}</p>
{/* <ChildMemo count={count}/> */}
<ChildMemo/>
</>
)
}
4. Sử dụng useMemo để giảm lặp lại các compute
useMemo sẽ chỉ lặp lại các compute khi các params thay đổi. Điều này giúp bạn giảm lặp lại các compute khi các params không thay đổi.
import React, { useState, useMemo } from 'react';
const Child = function (props) {
const {info} = {...props}
console.log(`Hoa hồng nhận取: ${info.age}`)
return (<div>Hoa hồng đã nhận取</div>)
};
export default () => {
const [age, setAge] = useState(6)
const [sex, setSex] = useState('boy')
const info = useMemo(() => {
return ({name: 'echo',age: age,})
}, [age])
return(
<div>
<button onClick={() => {setAge(age => age + 1)}}> tuổi tăng 1</button>
<button onClick={() => {setSex(sex => sex === 'boy' ? 'girl' : sex)}}> thay đổi giới</button><br></br>
<div>
`Tên là: ${info.name} tuổi là: ${info.age} giới là: ${sex} `;
</div>
<Child info={info}></Child>
</div>
)
}
5. Sử dụng useCallback để giảm lặp lại các hàm
useCallback sẽ chỉ lặp lại các hàm khi các params không thay đổi. Điều này giúp bạn giảm lặp lại các hàm khi các params không thay đổi.
import React, { useState, useCallback, memo } from 'react';
const Child = memo(function ({ onClick }) {
console.log("Hoa hồng渲染");
return <button onClick={onClick}>Hoa hồng</button>;
});
export default function Count() {
const [name, setName] = useState(0);
const [number, setNumber] = useState(0);
const addClick = useCallback(() => {
setNumber(number + 1);
}, []);
return (
<>
<button onClick={() => setName(name + 1)}>Tăng số</button>
<Child onClick={addClick} />
</>
);
}
6. Tối ưu hóa路由 với DismissAll
Trong trường hợp có nhiều trang, bạn có thể sử dụng dismissAll để xóa các tab không cần thiết, tránh lặp lại các路由.
import { router } from 'expo-router';
function getScreen(screenId) {
const tabs = ['home', 'topUp', 'order', 'me', 'login', 'profile', 'businessAccount'];
if (tabs.includes(screenId)) {
router.dismissAll();
}
}
7. Quản lý các trang常驻
Trong trường hợp sử dụng Expo, bạn có thể sử dụng các trang常驻 để lưu trữ dữ liệu, tránh lặp lại các dom.
const [isDomVisible, setIsDomVisible] = useState(true);
useFocusEffect(
useCallback(() => {
setIsDomVisible(true);
return () => {
setIsDomVisible(false);
};
}, []),
);
return isDomVisible ? <GestureHandlerRootView /> : <Loading isLoading={true} />;
8. Sử dụng FlatList thay vì ScrollView
FlatList sẽ giúp bạn tránh các vấn đề về performанс khi có các list lớn.
import IGFlatList from '@/CustomElements/IGFlatList';
<IGFlatList
data={orders}
loading={loading}
hasMoreData={hasMoreData}
handleLoadMore={handleLoadMore}
renderItem={ListItem}
keyExtractor={(item) => item.orderNo.toString()}
scrollToTopVar={scrollToTopVar}
/>
9. Sử dụng BottomSheetFlatList cho các list có Yêu cầu đặc biệt
Trong trường hợp có các list Yêu cầu special sliding, bạn có thể sử dụng BottomSheetFlatList thay vì ScrollView.
import BottomSheet, { BottomSheetFlatList } from '@gorhom/bottom-sheet';
<BottomSheetFlatList
data={storesData}
keyExtractor={(item) => item.staPkId.toString()}
renderItem={renderItem}
/>
10. Tối ưu hóa cache Globally
Bạn có thể sử dụng Redox-persist để cache Globally và sử dụng AsyncStorage để cache các dữ liệu.
import { persistStore, persistReducer } from 'redux-persist';
const persistedReducer = persistReducer(persistConfig, RTAL);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE', 'persist/PAUSE', 'persist/PURGE', 'persist/REGISTER'],
},
}),
});
11. Tối ưu hóa cache接口
Bạn có thể sử dụng AsyncStorage để cache các接口, Yêu cầu được tải lên khi cần.
export const setInitStores = async (value) => {
try {
await AsyncStorage.setItem('initStores', JSON.stringify(value));
} catch (error) {
console.error('Error setting initStores:', error);
}
};
12. Tối ưu hóa entrance Globally
Bạn có thể sử dụng globalRequest để xử lý các Yêu cầu entrance và tránh lặp lại các Yêu cầu.
const globalRequest = useCallback(async () => {
try {
dispatch(userActions.updateOprPkId({ oprPkId }));
const localTheme = await storageGetTheme();
if (localTheme) {
setTheme(handleTheme(localTheme));
setThemeReady(true);
} else {
setIsLoading(true);
}
const [oprInfoRes, themeRes] = await Promise.all([getOperInfo(), getTheme()]);
const { user } = store.getState();
if (user.token) {
const [accountRes] = await Promise.all([getAccountBaseInfo()]);
const accountInfo = accountRes.data.data[0];
dispatch(userActions.updateAccountInfo({ accountInfo }));
}
const oprInfo = oprInfoRes.data.data[0];
const themeData = themeRes.data.data[0];
setTheme(handleTheme(themeData));
setThemeReady(true);
storageSetTheme(themeData);
dispatch(userActions.SET_THEME(themeData));
dispatch(userActions.updateOprInfo({ oprInfo }));
if (oprInfo.currency) {
dispatch(i18nActions.updateCurrency({ currency: oprInfo.currency }));
}
if (oprInfo.currencySymbol) {
dispatch(
i18nActions.updateCurrencySymbol({
currencySymbol: oprInfo.currencySymbol,
}),
);
}
} catch (error) {
console.error('Error globalRequest', error);
ToastManager.show(t('networkError'));
setTheme(handleTheme(await storageGetTheme()));
} finally {
setIsLoading(false);
setThemeReady(true);
}
}, []);
useEffect(() => {
globalRequest();
}, []);