Skip to content

Instantly share code, notes, and snippets.

@wilsolutions
Last active July 8, 2025 18:15
Show Gist options
  • Save wilsolutions/a27e5078e9c0c0cc4e8153ed86ef185f to your computer and use it in GitHub Desktop.
Save wilsolutions/a27e5078e9c0c0cc4e8153ed86ef185f to your computer and use it in GitHub Desktop.
React Native Notes
# Optimizations
1. FlatList
const VehicleItem = React.memo(({ item }) => (
<View style={{ height: ITEM_HEIGHT }}>
<Card style={styles.card}>
<Text style={styles.plate}>{item.plate}</Text>
<Text>Status: {statusMap[item.status]}</Text>
<Text style={[styles.battery, { color: getBatteryColor(item.battery) }]}>
Battery: {item.battery}%
</Text>
</Card>
</View>
));
----
<FlatList data={vehicles} renderItem={({ item }) => <VehicleItem item={item}
keyExtractor={item => item.id}
getItemLayout={(_, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index
})}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={7}
removeClippedSubviews={true}
/>} />
1.2 Use FlashList
1.3 Use recyclerlistview
2. Memoize Components & Functions
import React, { memo, useCallback } from 'react';
// Memoize component
const MyComponent = memo(({ data }) => (
<Text>{data}</Text>
));
// Memoize function
const Parent = () => {
const handlePress = useCallback(() => {
console.log("Optimized press!");
}, []);
return <MyComponent onPress={handlePress} />;
};
3. Optimize FlatList Performance
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <ListItem item={item} />}
windowSize={5} // Render 5 items ahead/behind
initialNumToRender={10} // First render count
maxToRenderPerBatch={10} // Items per batch
updateCellsBatchingPeriod={50} // Batch update delay (ms)
removeClippedSubviews={true} // Unmount offscreen views (Android)
/>
4. Avoid Inline Functions & Styles
❌ Bad: Recreates on every render
<Button onPress={() => doSomething()} />
<View style={{ padding: 10 }} />
✅ Good: Uses useCallback and StyleSheet
const handlePress = useCallback(() => doSomething(), []);
const styles = StyleSheet.create({ padding: 10 });
5. Use React.memo for Heavy Components
const HeavyComponent = React.memo(({ data }) => {
return <ExpensiveRenderLogic data={data} />;
});
6. Lazy Load Screens & Components
// For screens (React Navigation)
const HomeScreen = React.lazy(() => import('./HomeScreen'));
// For components
const ExpensiveComponent = React.lazy(() => import('./ExpensiveComponent'));
7. Optimize Re-Renders with useMemo
const processedData = useMemo(() =>
data.filter(item => item.isActive),
[data]); // Only recomputes if `data` changes
8. Reduce JS ↔ Native Thread Communication
Avoid frequent setState in rapid succession (e.g., animations).
Use InteractionManager for heavy post-animation work:
InteractionManager.runAfterInteractions(() => {
// Heavy task after animation
});
9. Optimize Images
<Image
source={{ uri: 'https://example.com/image.jpg' }}
resizeMode="contain"
fadeDuration={0} // Disable fade (Android)
progressiveRenderingEnabled={true} // iOS only
/>
9.1 Use react-native-fast-image
# References
- Fetch data
const [todos, setTodos] = useState<Todo[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchTodos = async () => {
try {
const response = await fetch('https://dummyjson.com/todos?limit=5');
const data = await response.json();
setTodos(data.todos);
} catch (err) {
setError('Failed to fetch todos');
console.error(err);
} finally {
setLoading(false);
}
};
fetchTodos();
}, []);
1. Functional Component with Hooks
import React, { useState, useEffect } from 'react';
import { View, Text } from 'react-native';
const MyComponent = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
setData(await response.json());
};
return (
<View>
<Text>{data ? data.message : 'Loading...'}</Text>
</View>
);
};
export default MyComponent;
2. Navigation (React Navigation v6)
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const App = () => (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
3. Custom Hook (e.g., for API Calls)
const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
const response = await fetch(url);
setData(await response.json());
setLoading(false);
};
fetchData();
}, [url]);
return { data, loading };
};
4. Styled with StyleSheet
import { StyleSheet, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
});
const MyComponent = () => <View style={styles.container} />;
5. Handling Press Events
<TouchableOpacity onPress={() => console.log('Pressed!')}>
<Text>Press Me</Text>
</TouchableOpacity>
6. Platform-Specific Code
import { Platform } from 'react-native';
const styles = StyleSheet.create({
text: {
fontSize: Platform.OS === 'ios' ? 16 : 14,
},
});
7. Context API for State Management
import React, { createContext, useContext, useState } from 'react';
const AppContext = createContext();
const AppProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AppContext.Provider value={{ user, setUser }}>
{children}
</AppContext.Provider>
);
};
const useAppContext = () => useContext(AppContext);
8. Animations with Reanimated v2
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
const MyComponent = () => {
const width = useSharedValue(100);
const expand = () => {
width.value = withSpring(width.value + 50);
};
return (
<Animated.View style={{ width }}>
<Button title="Expand" onPress={expand} />
</Animated.View>
);
};
# Issues:
- Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication). A frequent cause of the error is that the application entry file path is incorrect.
Fix: watchman watch-del-all; react-native start --reset-cache
# IPA generation
1. Create the bundle
execAndLogCommand('Creating bundle...', `(npx react-native bundle \
--entry-file='index.js' \
--bundle-output=${bundleOutput} \
--dev=false \
--platform='${platform}' \
--assets-dest ${platform})`
);
2. Export the archive
execShell(`(export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild clean archive -workspace ${platform}/${appName}.xcworkspace \
-scheme ${appName} \
-sdk iphoneos \
-configuration ${configuration} \
-archivePath ${archivePath})`,
{silent: false}
);
3. Export the .ipa pkg
execAndLogCommand('Exporting IPA...', `(xcodebuild -exportArchive \
-archivePath $PWD/build/${appName}.xcarchive \
-exportOptionsPlist ${exportOptionsPlist} \
-exportPath $PWD/build -allowProvisioningUpdates)`
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment