Getting Started
React Native Setup
# Install React Native CLI
npm install -g react-native-cli
# Create a new React Native project
npx react-native init MyProject
# Or create a project with TypeScript
npx react-native init MyProject --template react-native-template-typescript
# Run on Android
npx react-native run-android
# Run on iOS
npx react-native run-ios
# Using Expo CLI
npm install -g expo-cli
expo init MyProject
expo start
npm install -g react-native-cli
# Create a new React Native project
npx react-native init MyProject
# Or create a project with TypeScript
npx react-native init MyProject --template react-native-template-typescript
# Run on Android
npx react-native run-android
# Run on iOS
npx react-native run-ios
# Using Expo CLI
npm install -g expo-cli
expo init MyProject
expo start
Note: For React Native CLI, you need Android Studio and Xcode installed. Expo provides a simpler setup but with some limitations.
Basic App Structure
// App.js - Basic React Native App
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<Text style={styles.text}>Hello React Native!</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
text: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
export default App;
// index.js - Entry point
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<Text style={styles.text}>Hello React Native!</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
text: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
export default App;
// index.js - Entry point
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
Core Components
Basic Components
// View - Container component
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff'
}}
>
<!-- Content here -->
</View>
// Text - Display text
<Text
style={{
fontSize: 18,
fontWeight: 'bold',
color: '#333'
}}
numberOfLines={1}
>
Hello World!
</Text>
// Image - Display images
<Image
source={{ uri: 'https://example.com/image.jpg' }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
/>
// Local image
<Image
source={require('./assets/image.png')}
style={{ width: 200, height: 200 }}
/>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff'
}}
>
<!-- Content here -->
</View>
// Text - Display text
<Text
style={{
fontSize: 18,
fontWeight: 'bold',
color: '#333'
}}
numberOfLines={1}
>
Hello World!
</Text>
// Image - Display images
<Image
source={{ uri: 'https://example.com/image.jpg' }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
/>
// Local image
<Image
source={require('./assets/image.png')}
style={{ width: 200, height: 200 }}
/>
Note: View is similar to div in HTML, Text must be used for all text, and Image requires explicit dimensions.
Interactive Components
// Button
<Button
title="Press Me"
onPress={() => alert('Button pressed!')}
color="#841584"
/>
// Touchable Components
<TouchableOpacity
onPress={() => alert('Pressed with opacity effect')}
style={{ padding: 10, backgroundColor: '#ddd' }}
>
<Text>Press Me</Text>
</TouchableOpacity>
<TouchableHighlight
onPress={() => alert('Pressed with highlight effect')}
underlayColor="white"
>
<View style={{ padding: 10 }}>
<Text>Press Me</Text>
</View>
</TouchableHighlight>
// TextInput
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={(text) => setText(text)}
value={text}
placeholder="Enter text here"
keyboardType="default"
/>
// Switch
<Switch
value={isEnabled}
onValueChange={setIsEnabled}
trackColor={{ false: '#767577', true: '#81b0ff' }}
/>
<Button
title="Press Me"
onPress={() => alert('Button pressed!')}
color="#841584"
/>
// Touchable Components
<TouchableOpacity
onPress={() => alert('Pressed with opacity effect')}
style={{ padding: 10, backgroundColor: '#ddd' }}
>
<Text>Press Me</Text>
</TouchableOpacity>
<TouchableHighlight
onPress={() => alert('Pressed with highlight effect')}
underlayColor="white"
>
<View style={{ padding: 10 }}>
<Text>Press Me</Text>
</View>
</TouchableHighlight>
// TextInput
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={(text) => setText(text)}
value={text}
placeholder="Enter text here"
keyboardType="default"
/>
// Switch
<Switch
value={isEnabled}
onValueChange={setIsEnabled}
trackColor={{ false: '#767577', true: '#81b0ff' }}
/>
Note: Button has limited styling options. For custom buttons, use TouchableOpacity or TouchableHighlight with custom styling.
List Components
// FlatList - for simple lists
<FlatList
data={[
{ id: '1', title: 'Item 1' },
{ id: '2', title: 'Item 2' },
{ id: '3', title: 'Item 3' },
]}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<Text>{item.title}</Text>
)}
/>
// SectionList - for sectioned lists
<SectionList
sections={[
{
title: 'Section 1',
data: ['Item 1', 'Item 2'],
},
{
title: 'Section 2',
data: ['Item 3', 'Item 4'],
},
]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => (
<Text style={{ fontWeight: 'bold' }}>
{section.title}
</Text>
)}
keyExtractor={(item, index) => index.toString()}
/>
// ScrollView - for scrollable content
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{ padding: 20 }}
showsVerticalScrollIndicator={false}
>
<Text>Long content here...</Text>
</ScrollView>
<FlatList
data={[
{ id: '1', title: 'Item 1' },
{ id: '2', title: 'Item 2' },
{ id: '3', title: 'Item 3' },
]}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<Text>{item.title}</Text>
)}
/>
// SectionList - for sectioned lists
<SectionList
sections={[
{
title: 'Section 1',
data: ['Item 1', 'Item 2'],
},
{
title: 'Section 2',
data: ['Item 3', 'Item 4'],
},
]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => (
<Text style={{ fontWeight: 'bold' }}>
{section.title}
</Text>
)}
keyExtractor={(item, index) => index.toString()}
/>
// ScrollView - for scrollable content
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{ padding: 20 }}
showsVerticalScrollIndicator={false}
>
<Text>Long content here...</Text>
</ScrollView>
Styling & Layout
// Flexbox layout example
<View style={{
flex: 1,
flexDirection: 'row', // or 'column'
justifyContent: 'space-between', // or 'flex-start', 'center', 'flex-end', 'space-around', 'space-evenly'
alignItems: 'center', // or 'flex-start', 'flex-end', 'stretch', 'baseline'
backgroundColor: '#f0f0f0',
}}>
<View style={{ width: 50, height: 50, backgroundColor: 'red' }} />
<View style={{ width: 50, height: 50, backgroundColor: 'green' }} />
<View style={{ width: 50, height: 50, backgroundColor: 'blue' }} />
</View>
// Using StyleSheet
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
color: '#333',
},
button: {
backgroundColor: '#007AFF',
padding: 15,
borderRadius: 5,
alignItems: 'center',
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
},
});
// Platform-specific styles
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
ios: {
backgroundColor: 'red',
},
android: {
backgroundColor: 'blue',
},
}),
},
});
<View style={{
flex: 1,
flexDirection: 'row', // or 'column'
justifyContent: 'space-between', // or 'flex-start', 'center', 'flex-end', 'space-around', 'space-evenly'
alignItems: 'center', // or 'flex-start', 'flex-end', 'stretch', 'baseline'
backgroundColor: '#f0f0f0',
}}>
<View style={{ width: 50, height: 50, backgroundColor: 'red' }} />
<View style={{ width: 50, height: 50, backgroundColor: 'green' }} />
<View style={{ width: 50, height: 50, backgroundColor: 'blue' }} />
</View>
// Using StyleSheet
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
color: '#333',
},
button: {
backgroundColor: '#007AFF',
padding: 15,
borderRadius: 5,
alignItems: 'center',
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
},
});
// Platform-specific styles
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
ios: {
backgroundColor: 'red',
},
android: {
backgroundColor: 'blue',
},
}),
},
});
Note: Flexbox is the primary layout system in React Native. StyleSheet.create provides performance optimizations and validation.
State Management
useState & useEffect
// useState hook
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>You clicked {count} times</Text>
<Button
title="Click me"
onPress={() => setCount(count + 1)}
/>
</View>
);
};
// useEffect hook
import React, { useState, useEffect } from 'react';
const Example = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
// Similar to componentDidMount and componentDidUpdate
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
// Effect with cleanup (similar to componentWillUnmount)
useEffect(() => {
const subscription = API.subscribe();
// Cleanup function
return () => {
subscription.unsubscribe();
};
}, []);
// Fetch data on component mount
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const json = await response.json();
setData(json);
setLoading(false);
} catch (error) {
console.error(error);
setLoading(false);
}
};
fetchData();
}, []); // Empty array means this effect runs once on mount
if (loading) {
return <Text>Loading...</Text>;
}
return (
<View>
{data.map(item => (
<Text key={item.id}>{item.name}</Text>
))}
</View>
);
};
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>You clicked {count} times</Text>
<Button
title="Click me"
onPress={() => setCount(count + 1)}
/>
</View>
);
};
// useEffect hook
import React, { useState, useEffect } from 'react';
const Example = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
// Similar to componentDidMount and componentDidUpdate
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
// Effect with cleanup (similar to componentWillUnmount)
useEffect(() => {
const subscription = API.subscribe();
// Cleanup function
return () => {
subscription.unsubscribe();
};
}, []);
// Fetch data on component mount
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const json = await response.json();
setData(json);
setLoading(false);
} catch (error) {
console.error(error);
setLoading(false);
}
};
fetchData();
}, []); // Empty array means this effect runs once on mount
if (loading) {
return <Text>Loading...</Text>;
}
return (
<View>
{data.map(item => (
<Text key={item.id}>{item.name}</Text>
))}
</View>
);
};
Context API & Redux
// Context API
import React, { createContext, useContext, useState } from 'react';
// Create a Context
const AuthContext = createContext();
// Create a provider component
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const login = (userData) => {
setUser(userData);
};
const logout = () => {
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
// Custom hook to use the auth context
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
// Using the context in a component
const UserProfile = () => {
const { user, logout } = useAuth();
return (
<View>
<Text>Welcome {user?.name}</Text>
<Button title="Logout" onPress={logout} />
</View>
);
};
// Redux Toolkit setup
import { configureStore, createSlice } from '@reduxjs/toolkit';
// Create a slice
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// Export actions
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// Create store
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
// Using Redux in components with React-Redux hooks
import { useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increment" onPress={() => dispatch(increment())} />
<Button title="Decrement" onPress={() => dispatch(decrement())} />
</View>
);
};
import React, { createContext, useContext, useState } from 'react';
// Create a Context
const AuthContext = createContext();
// Create a provider component
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const login = (userData) => {
setUser(userData);
};
const logout = () => {
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
// Custom hook to use the auth context
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
// Using the context in a component
const UserProfile = () => {
const { user, logout } = useAuth();
return (
<View>
<Text>Welcome {user?.name}</Text>
<Button title="Logout" onPress={logout} />
</View>
);
};
// Redux Toolkit setup
import { configureStore, createSlice } from '@reduxjs/toolkit';
// Create a slice
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// Export actions
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// Create store
const store = configureStore({
reducer: {
counter: counterSlice.reducer,
},
});
// Using Redux in components with React-Redux hooks
import { useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increment" onPress={() => dispatch(increment())} />
<Button title="Decrement" onPress={() => dispatch(decrement())} />
</View>
);
};
Note: Use Context API for simple state that doesn't change often. For complex state management with frequent updates, use Redux Toolkit.