Documentation Index
Fetch the complete documentation index at: https://copylabs.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Performance Guide
This guide covers performance optimization techniques for React Native applications using Radix Themes Native.
React Optimization
Memoization
Use memoization to prevent unnecessary re-renders:
import { memo, useMemo, useCallback } from 'react';
// Memoize components
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
return <Text>{data}</Text>;
});
// Memoize values
function MyComponent({ items }) {
const sortedItems = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
return (
<Flex direction="column">
{sortedItems.map(item => (
<Text key={item.id}>{item.name}</Text>
))}
</Flex>
);
}
// Memoize callbacks
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
return <ChildComponent onClick={handleClick} />;
}
Virtualization
Use virtualization for long lists:
import { FlashList } from '@shopify/flash-list';
function VirtualizedList({ items }) {
const renderItem = useCallback(({ item }) => (
<Card>
<Text>{item.name}</Text>
</Card>
), []);
return (
<FlashList
data={items}
renderItem={renderItem}
estimatedItemSize={80}
/>
);
}
Use StyleSheet
Use StyleSheet.create for static styles:
import { StyleSheet } from 'react-native';
// Good - Styles are created once
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
title: {
fontSize: 24,
fontWeight: 'bold',
},
});
function MyComponent() {
return (
<View style={styles.container}>
<Text style={styles.title}>Title</Text>
</View>
);
}
// Avoid - Styles created on every render
function MyComponent() {
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Title</Text>
</View>
);
}
Avoid Inline Functions in Props
// Good - Stable function reference
const handlePress = useCallback(() => {
console.log('Pressed');
}, []);
<Button onPress={handlePress}>Click</Button>
// Avoid - New function on every render
<Button onPress={() => console.log('Pressed')}>Click</Button>
Image Optimization
Use Proper Image Sizes
// Good - Specify dimensions
<Image
source={{ uri: imageUrl, width: 200, height: 200 }}
style={{ width: 200, height: 200 }}
/>
// Avoid - No dimensions
<Image source={{ uri: imageUrl }} />
Use FastImage for Remote Images
import FastImage from 'react-native-fast-image';
<FastImage
source={{ uri: imageUrl, priority: FastImage.priority.normal }}
style={{ width: 200, height: 200 }}
/>
Cache Images
<Image
source={{
uri: imageUrl,
cache: 'force-cache'
}}
/>
List Optimization
Key Prop
Always use stable keys:
// Good - Stable unique keys
{items.map(item => (
<Card key={item.id}>
<Text>{item.name}</Text>
</Card>
))}
// Avoid - Index as key
{items.map((item, index) => (
<Card key={index}>
<Text>{item.name}</Text>
</Card>
))}
getItemLayout
Provide item layout for flat lists:
<FlatList
data={items}
renderItem={renderItem}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
Remove Clipped Subviews
<FlatList
data={items}
renderItem={renderItem}
removeClippedSubviews={true}
/>
Use Native Driver
import { Animated } from 'react-native';
// Good - Uses native driver
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true, // Runs on native thread
}).start();
// Avoid - JS-driven animation
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: false,
}).start();
Use LayoutAnimation
import { LayoutAnimation, UIManager } from 'react-native';
function AnimatedList({ items }) {
const handleAdd = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setItems([...items, newItem]);
};
return (
<Flex direction="column">
{items.map(item => (
<Card key={item.id}>
<Text>{item.name}</Text>
</Card>
))}
</Flex>
);
}
State Management
Avoid Prop Drilling
Use context or state management:
// Good - Context for shared state
const UserContext = createContext();
function App() {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
<Navigation />
</UserContext.Provider>
);
}
// Avoid - Prop drilling
function App() {
const [user, setUser] = useState(null);
return <Parent user={user} setUser={setUser} />;
}
function Parent({ user, setUser }) {
return <Child user={user} setUser={setUser} />;
}
function Child({ user, setUser }) {
return <Grandchild user={user} setUser={setUser} />;
}
Local State
Keep state as close as possible to where it’s used:
// Good - Local state
function SearchInput() {
const [query, setQuery] = useState('');
return <TextField value={query} onChangeText={setQuery} />;
}
// Avoid - Global state for local concerns
function SearchInput() {
const query = useGlobalStore(state => state.query);
const setQuery = useGlobalStore(state => state.setQuery);
return <TextField value={query} onChangeText={setQuery} />;
}
Bundle Size
Tree Shaking
Import only what you need:
// Good - Tree-shakeable
import { Button } from 'radix-native-ui';
// Avoid - Imports everything
import * as Radix from 'radix-native-ui';
Lazy Loading
Lazy load screens and components:
import { lazy, Suspense } from 'react';
const SettingsScreen = lazy(() => import('./SettingsScreen'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<SettingsScreen />
</Suspense>
);
}
Profiling
Use React DevTools to identify performance issues:
- Open React DevTools
- Go to Profiler tab
- Record a profile
- Analyze component renders
Flipper
Use Flipper for React Native debugging:
- Network inspection
- Layout inspection
- Performance monitoring
Enable performance monitor in development:
import { PerformanceObserver } from 'react-native-performance';
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach(entry => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
observer.observe({ entryTypes: ['measure'] });
Best Practices Checklist