🚀 Core Concepts
What is React Native?
- Cross-platform mobile framework by Facebook (Meta)
- Write once, run on iOS and Android
- Uses JavaScript and React
- Compiles to native code (not a webview)
How it Works
JavaScript Code → Bridge → Native APIs → Native UI
📱 Basic Setup & Structure
Project Structure
MyApp/
├── android/ # Android-specific code
├── ios/ # iOS-specific code
├── src/ # JavaScript source code
├── package.json # Dependencies
└── index.js # Entry point
Basic App Component
import React from 'react';
import { View, Text } from 'react-native';
const App = () => {
return (
<View style={{ flex: 1, justifyContent: 'center' }}>
<Text>Hello React Native!</Text>
</View>
);
};
export default App;
🧩 Core Components
Essential Components
import {
View, // Like <div>
Text, // For displaying text
Image, // For images
ScrollView, // Scrollable container
TextInput, // Input field
TouchableOpacity, // Touchable button
FlatList, // Optimized list
Modal, // Modal dialog
ActivityIndicator, // Loading spinner
} from 'react-native';
View & Text
<View style={styles.container}>
<Text style={styles.title}>Title</Text>
<Text numberOfLines={2}>Long text...</Text>
</View>
TextInput
const [text, setText] = useState('');
<TextInput
value={text}
onChangeText={setText}
placeholder="Enter text"
secureTextEntry={true} // For passwords
keyboardType="numeric" // numeric, email-address, etc.
/>
TouchableOpacity & Pressable
// TouchableOpacity (legacy)
<TouchableOpacity onPress={() => alert('Pressed!')}>
<Text>Press Me</Text>
</TouchableOpacity>
// Pressable (modern)
<Pressable
onPress={() => {}}
style={({ pressed }) => [
styles.button,
pressed && styles.pressed
]}
>
<Text>Press Me</Text>
</Pressable>
FlatList (Optimized Lists)
<FlatList
data={[{id: '1', title: 'Item 1'}]}
renderItem={({ item }) => <Text>{item.title}</Text>}
keyExtractor={item => item.id}
onRefresh={handleRefresh}
refreshing={isRefreshing}
ListEmptyComponent={<Text>No items</Text>}
/>
SectionList (Grouped Lists)
<SectionList
sections={[
{title: 'Section 1', data: ['Item 1', 'Item 2']},
]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => (
<Text>{section.title}</Text>
)}
keyExtractor={(item, index) => index.toString()}
/>
🎨 Styling
StyleSheet API
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#fff',
},
text: {
fontSize: 16,
color: '#333',
fontWeight: 'bold',
},
});
// Usage
<View style={styles.container}>
<Text style={[styles.text, { color: 'red' }]}>Hello</Text>
</View>
Flexbox Layout
// Main axis alignment
justifyContent: 'center' | 'flex-start' | 'flex-end' |
'space-between' | 'space-around' | 'space-evenly'
// Cross axis alignment
alignItems: 'center' | 'flex-start' | 'flex-end' | 'stretch'
// Flex direction
flexDirection: 'row' | 'column' | 'row-reverse' | 'column-reverse'
// Example
<View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<View style={{ flex: 1 }} />
<View style={{ flex: 2 }} />
</View>
Platform-Specific Styling
import { Platform, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
paddingTop: Platform.OS === 'ios' ? 50 : 30,
...Platform.select({
ios: { backgroundColor: 'red' },
android: { backgroundColor: 'blue' },
}),
},
});
🔄 State Management
useState Hook
const [count, setCount] = useState(0);
<Button title="+" onPress={() => setCount(count + 1)} />
useEffect Hook
useEffect(() => {
// Component mount
fetchData();
// Cleanup
return () => {
cancelSubscription();
};
}, [dependency]); // Re-run when dependency changes
useContext for Global State
// Create context
const ThemeContext = React.createContext();
// Provider
<ThemeContext.Provider value={{ theme: 'dark' }}>
<App />
</ThemeContext.Provider>
// Consumer
const { theme } = useContext(ThemeContext);
Redux Setup (Basic)
// Store
import { createStore } from 'redux';
const store = createStore(rootReducer);
// Provider
import { Provider } from 'react-redux';
<Provider store={store}>
<App />
</Provider>
// Component
import { useSelector, useDispatch } from 'react-redux';
const count = useSelector(state => state.count);
const dispatch = useDispatch();
dispatch({ type: 'INCREMENT' });
📱 Platform-Specific Code
Platform API
import { Platform } from 'react-native';
if (Platform.OS === 'ios') {
// iOS specific code
} else if (Platform.OS === 'android') {
// Android specific code
}
// Platform-specific files
// Button.ios.js
// Button.android.js
import Button from './Button'; // Auto picks correct file
Dimensions API
import { Dimensions } from 'react-native';
const { width, height } = Dimensions.get('window');
const isTablet = width >= 768;
// Listen to orientation changes
Dimensions.addEventListener('change', ({ window }) => {
console.log('New dimensions:', window);
});
🚀 Performance Optimization
Memoization
import React, { memo, useMemo, useCallback } from 'react';
// Memo for components
const ExpensiveComponent = memo(({ data }) => {
return <Text>{data}</Text>;
});
// useMemo for values
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);
// useCallback for functions
const handlePress = useCallback(() => {
doSomething(id);
}, [id]);
FlatList Optimization
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
// Performance props
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
initialNumToRender={10}
windowSize={10}
// Prevent re-renders
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
Image Optimization
import { Image } from 'react-native';
import FastImage from 'react-native-fast-image';
// Regular Image
<Image
source={{ uri: 'https://example.com/image.jpg' }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
/>
// FastImage (better performance)
<FastImage
source={{
uri: 'https://example.com/image.jpg',
priority: FastImage.priority.high,
}}
style={{ width: 200, height: 200 }}
resizeMode={FastImage.resizeMode.cover}
/>
🔧 Native Modules & APIs
Common APIs
// AsyncStorage
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('user', JSON.stringify(userData));
const user = JSON.parse(await AsyncStorage.getItem('user'));
// Permissions
import { PermissionsAndroid } from 'react-native';
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA
);
// Linking (URLs)
import { Linking } from 'react-native';
Linking.openURL('https://example.com');
Linking.openURL('tel:+1234567890');
// Alert
import { Alert } from 'react-native';
Alert.alert(
'Title',
'Message',
[
{ text: 'Cancel', style: 'cancel' },
{ text: 'OK', onPress: () => console.log('OK') },
]
);
Animations
import { Animated } from 'react-native';
const fadeAnim = useRef(new Animated.Value(0)).current;
// Fade in
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}).start();
<Animated.View style={{ opacity: fadeAnim }}>
<Text>Fading in</Text>
</Animated.View>
// Spring animation
Animated.spring(animValue, {
toValue: 100,
friction: 5,
tension: 40,
useNativeDriver: false,
}).start();
Gesture Handler
import {
PanGestureHandler,
State,
} from 'react-native-gesture-handler';
<PanGestureHandler
onGestureEvent={handleGesture}
onHandlerStateChange={handleStateChange}
>
<Animated.View style={animatedStyle}>
<Text>Drag me!</Text>
</Animated.View>
</PanGestureHandler>
🧪 Testing
Jest Setup
// Component test
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import Button from './Button';
test('Button renders correctly', () => {
const { getByText } = render(<Button title="Press me" />);
expect(getByText('Press me')).toBeDefined();
});
test('Button handles press', () => {
const onPress = jest.fn();
const { getByText } = render(
<Button title="Press me" onPress={onPress} />
);
fireEvent.press(getByText('Press me'));
expect(onPress).toHaveBeenCalled();
});
Snapshot Testing
import renderer from 'react-test-renderer';
test('Component snapshot', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
🐛 Debugging
Developer Menu
- iOS Simulator: Cmd + D
- Android Emulator: Cmd + M (Mac) / Ctrl + M (Windows)
- Device: Shake
Console Logging
console.log('Debug:', data);
console.warn('Warning:', issue);
console.error('Error:', error);
// Better debugging
console.table(arrayData);
console.group('Group');
console.log('Item 1');
console.log('Item 2');
console.groupEnd();
React DevTools
npm install -g react-devtools
react-devtools
Flipper Integration
- Built-in debugging tool
- Network inspection
- Layout inspector
- Performance profiling
💡 Best Practices
Component Structure
// Good component structure
const MyComponent = ({ title, onPress }) => {
// Hooks at the top
const [state, setState] = useState(false);
// Effects after hooks
useEffect(() => {
// Effect logic
}, []);
// Handlers
const handlePress = useCallback(() => {
onPress?.();
}, [onPress]);
// Render
return (
<View>
<Text>{title}</Text>
</View>
);
};
// PropTypes or TypeScript
MyComponent.propTypes = {
title: PropTypes.string.isRequired,
onPress: PropTypes.func,
};
Error Boundaries
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log('Error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <Text>Something went wrong.</Text>;
}
return this.props.children;
}
}
Performance Tips
- Use
FlatListinstead ofmap()for lists - Implement
getItemLayoutwhen possible - Use
InteractionManagerfor heavy operations - Optimize images (use appropriate sizes)
- Minimize bridge communication
- Use
useCallbackanduseMemoappropriately - Avoid inline styles and functions
- Enable Hermes on Android
🎯 Common Interview Topics
Key Differences: React vs React Native
- React: Web DOM elements (
<div>,<span>) - React Native: Native components (
<View>,<Text>) - Styling: CSS vs StyleSheet API
- No browser APIs in React Native
- Platform-specific code handling
Bridge Architecture Deep Dive
How the Bridge Works:
- JS Thread: Executes JavaScript code, business logic
- Shadow Thread: Calculates layout using Yoga (Flexbox engine)
- Main/UI Thread: Renders native components
Bridge Limitations (Why New Architecture):
- Asynchronous: All communication is async
- Serialization Overhead: JSON stringify/parse
- Single Bridge: Bottleneck for heavy operations
- No Synchronous Calls: Can't access native properties directly
Example Bridge Communication:
// JavaScript side
NativeModules.MyModule.doSomething('param', (result) => {
console.log(result); // Async callback
});
// Native side receives JSON
{
"module": "MyModule",
"method": "doSomething",
"args": ["param"],
"callbackId": 1
}
Virtual DOM in React Native
- Similar concept to React
- Diffs happen in JavaScript
- Updates sent to native side via bridge
- Native views updated accordingly
Common Performance Issues
- Too many bridge calls
- Large lists without optimization
- Heavy computations on JS thread
- Unnecessary re-renders
- Large images
- Memory leaks from listeners
Security Considerations
- Store sensitive data securely (Keychain/Keystore)
- Enable certificate pinning
- Obfuscate JavaScript code
- Validate all inputs
- Use HTTPS only
- Implement proper authentication
Deployment Process
# iOS
1. Archive in Xcode
2. Upload to App Store Connect
3. Submit for review
# Android
1. Generate signed APK/AAB
2. Upload to Google Play Console
3. Submit for review
# CodePush (for JS updates)
code-push release-react MyApp ios -d Production
📚 Advanced Topics
Custom Native Modules
// iOS (Objective-C)
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(multiply:(float)a b:(float)b
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
resolve(@(a * b));
}
// JavaScript
import { NativeModules } from 'react-native';
const { Calculator } = NativeModules;
const result = await Calculator.multiply(5, 10);
Deep Linking
// Configuration
const linking = {
prefixes: ['myapp://', 'https://myapp.com'],
config: {
screens: {
Home: '',
Profile: 'profile/:id',
},
},
};
<NavigationContainer linking={linking}>
{/* ... */}
</NavigationContainer>
Push Notifications
import messaging from '@react-native-firebase/messaging';
// Request permission
const authStatus = await messaging().requestPermission();
// Get token
const token = await messaging().getToken();
// Handle notifications
messaging().onMessage(async remoteMessage => {
console.log('Notification:', remoteMessage);
});
🔥 Hot Tips for Interviews
- Know the Bridge: Understand how JS communicates with native
- Performance: Be ready to discuss optimization strategies
- Platform Differences: Know iOS vs Android specifics
- State Management: Compare Context, Redux, MobX
- Navigation: Understand stack, tab, and drawer navigators
- Testing: Know unit, integration, and E2E testing approaches
- Deployment: Understand app store submission process
- Security: Discuss secure storage and network security
- Debugging Tools: Flipper, React DevTools, Chrome debugger
- Latest Features: Fabric, TurboModules, JSI
📱 New Architecture (Fabric & TurboModules)
Fabric (New Rendering System)
- Synchronous rendering
- Direct manipulation without bridge
- Better performance for animations
TurboModules
- Lazy loading of native modules
- Direct method invocation
- Type safety with CodeGen
JSI (JavaScript Interface)
- Direct communication between JS and Native
- No JSON serialization
- Shared memory access
Quick Reference Commands
# Create new app
npx react-native init MyApp
# Run iOS
npx react-native run-ios
# Run Android
npx react-native run-android
# Start Metro bundler
npx react-native start
# Link assets
npx react-native link
# Clear cache
npx react-native start --reset-cache
# Pod install (iOS)
cd ios && pod install
Remember: Practice coding these examples and understand the concepts deeply. Good luck with your interview! 🚀
Found this useful? Pass it on.