Advanced React Native Cheat Sheet

Last Updated: November 21, 2025

FlatList Optimization

<FlatList initialNumToRender={10} />
Set initial items to render
<FlatList maxToRenderPerBatch={10} />
Limit items rendered per batch
<FlatList windowSize={5} />
Set viewport window size multiplier
<FlatList removeClippedSubviews={true} />
Unmount offscreen views (Android)
<FlatList getItemLayout={(data, index) => ({length: 100, offset: 100 * index, index})} />
Skip measurement for known item heights
<FlatList keyExtractor={(item) => item.id} />
Provide stable unique keys
<FlatList updateCellsBatchingPeriod={50} />
Batch cell updates for better performance
const renderItem = useCallback(({item}) => <Item data={item} />, [])
Memoize render function
const Item = React.memo(({data}) => <View />)
Memoize list item component
<FlatList onEndReachedThreshold={0.5} />
Configure infinite scroll threshold
<FlatList onEndReached={loadMore} />
Handle infinite scroll
<FlatList ListFooterComponent={<ActivityIndicator />} />
Add loading indicator at bottom

Animated API

const fadeAnim = useRef(new Animated.Value(0)).current
Create animated value
Animated.timing(fadeAnim, {toValue: 1, duration: 500, useNativeDriver: true}).start()
Timing animation with native driver
Animated.spring(value, {toValue: 1, friction: 5, useNativeDriver: true})
Spring animation
Animated.decay(velocity, {velocity: {x: gestureState.vx, y: gestureState.vy}, useNativeDriver: true})
Decay animation for gestures
Animated.parallel([anim1, anim2]).start()
Run animations in parallel
Animated.sequence([anim1, anim2]).start()
Run animations sequentially
Animated.stagger(100, animations).start()
Stagger animation start times
Animated.loop(animation).start()
Loop animation infinitely
const opacity = fadeAnim.interpolate({inputRange: [0, 1], outputRange: [0, 1]})
Interpolate animated values
<Animated.View style={{opacity: fadeAnim}} />
Apply animated value to style
Animated.event([{nativeEvent: {contentOffset: {y: scrollY}}}], {useNativeDriver: true})
Map gesture/scroll to animated value
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity)
Create animated custom component
Animated.multiply(value1, value2)
Multiply animated values
Animated.add(value1, value2)
Add animated values
Animated.diffClamp(value, min, max)
Clamp value changes for collapsing headers

Native Modules (iOS)

@interface MyModule : NSObject <RCTBridgeModule>
Create native module interface
RCT_EXPORT_MODULE();
Export module to React Native
RCT_EXPORT_METHOD(methodName:(NSString *)param callback:(RCTResponseSenderBlock)callback)
Export native method
RCT_REMAP_METHOD(jsName, nativeName:(NSString *)param)
Export method with different JS name
callback(@[[NSNull null], result]);
Call callback with result
RCTPromiseResolveBlock resolve, RCTPromiseRejectBlock reject
Use promises in native methods
[bridge.eventDispatcher sendAppEventWithName:@"EventName" body:@{@"key": @"value"}]
Send events to JavaScript
- (NSArray<NSString *> *)supportedEvents { return @[@"EventName"]; }
Declare supported events

Native Modules (Android)

public class MyModule extends ReactContextBaseJavaModule
Create native module class
@Override public String getName() { return "MyModule"; }
Define module name
@ReactMethod public void methodName(String param, Callback callback)
Export method to JavaScript
@ReactMethod public void methodName(String param, Promise promise)
Use promises in native methods
promise.resolve(result);
Resolve promise from native code
promise.reject("ERROR_CODE", "Error message");
Reject promise with error
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("EventName", params);
Send events to JavaScript
public class MyPackage implements ReactPackage
Create package for module registration
modules.add(new MyModule(reactContext));
Register module in package

Bridging JavaScript to Native

import {NativeModules} from 'react-native';
Import native modules API
const {MyModule} = NativeModules;
Access native module
MyModule.methodName(param, (error, result) => {...})
Call native method with callback
const result = await MyModule.methodName(param)
Call native method with promise
import {NativeEventEmitter} from 'react-native';
Import event emitter for native events
const eventEmitter = new NativeEventEmitter(MyModule);
Create event emitter instance
const subscription = eventEmitter.addListener('EventName', (event) => {...})
Listen to native events
subscription.remove();
Remove event listener

Performance Monitoring

import {PerformanceObserver, performance} from 'react-native-performance';
Import performance monitoring
performance.mark('operationStart')
Mark performance point
performance.measure('operation', 'operationStart', 'operationEnd')
Measure performance between marks
const observer = new PerformanceObserver((list) => {...})
Create performance observer
observer.observe({entryTypes: ['measure']})
Observe specific performance entries
import {enableScreens} from 'react-native-screens';
Enable native screen optimization
InteractionManager.runAfterInteractions(() => {...})
Defer work until after animations
console.time('operation'); /* code */ console.timeEnd('operation')
Simple performance timing
import {Systrace} from 'react-native';
Use systrace for profiling

Memory & Bundle Optimization

import {Image} from 'react-native-fast-image';
Use optimized image component
<Image source={{uri: url, priority: FastImage.priority.high}} />
Set image loading priority
FastImage.preload([{uri: url1}, {uri: url2}])
Preload images
const Component = React.lazy(() => import('./Component'))
Lazy load components
import {enableFreeze} from 'react-native-screens';
Freeze inactive screens
hermes: true
Enable Hermes engine in android/app/build.gradle
def enableProguardInReleaseBuilds = true
Enable ProGuard for smaller APK
def enableSeparateBuildPerCPUArchitecture = true
Build separate APKs per architecture

Advanced Hooks Patterns

const value = useMemo(() => expensiveCalculation(), [dep])
Memoize expensive calculations
const callback = useCallback(() => {...}, [dep])
Memoize callback functions
const ref = useRef()
Create mutable ref object
useImperativeHandle(ref, () => ({method() {...}}))
Customize ref handle
useLayoutEffect(() => {...}, [deps])
Synchronous effect before paint
const [state, dispatch] = useReducer(reducer, initialState)
Complex state logic with reducer
const id = useId()
Generate unique IDs for accessibility

Debugging & DevTools

import {enableNetworkInspector} from 'react-native-network-inspector';
Enable network request inspection
import Reactotron from 'reactotron-react-native';
Use Reactotron for debugging
console.log(JSON.stringify(obj, null, 2))
Log formatted JSON objects
__DEV__ ? console.log('Debug') : null
Conditional development logging
import {LogBox} from 'react-native'; LogBox.ignoreLogs(['Warning'])
Ignore specific warnings
adb reverse tcp:8081 tcp:8081
Reverse port for Android debugging
npx react-native start --reset-cache
Start metro bundler with cache reset
Pro Tip: Always use useNativeDriver: true for Animated API when animating transform and opacity properties. Enable Hermes engine for better performance and smaller bundle size. For long lists, combine FlatList optimization techniques like getItemLayout, windowSize, and React.memo!
← Back to Web Frameworks | Browse all categories | View all cheat sheets