React Native is a JavaScript framework for building cross-platform mobile applications (iOS & Android) using React.
It allows developers to write native mobile applications using React and JavaScript instead of platform-specific languages like Swift (iOS) or Kotlin (Android).
To start with React Native, you need to set up your development environment. There are two main ways to develop a React Native app:
Expo is a framework and platform that makes it easy to build and run React Native applications without installing Android Studio or Xcode.
# Install Node.js (if not installed)
# Install Expo CLI
npm install -g expo-cli
# Create a new project
expo init MyFirstApp
# Navigate into the project folder
cd MyFirstApp
# Start the development server
npm start
This method requires installing Android Studio for Android development and Xcode for iOS development.
# Install React Native CLI npm install -g react-native-cli # Create a new project npx react-native init MyFirstApp # Navigate into the project folder cd MyFirstApp # Run the app on an Android emulator npx react-native run-android # Run the app on an iOS simulator (Mac only) npx react-native run-ios
After setting up the environment, let’s create a basic React Native app.
import React from 'react'; import { View, Text } from 'react-native'; const App = () => { return ( <View> <Text>Hello, React Native!</Text> </View> ); }; export default App;
View: The fundamental UI building block, like <div> in web development.
Text: Used to display text in React Native.
Once the project is created, use the following command to run your app:
# Run on Expo npm start # Run on Android Emulator (React Native CLI) npx react-native run-android # Run on iOS Simulator (React Native CLI) npx react-native run-ios
React Native provides core components to build UI elements. Some of the most common ones are:
import React from 'react'; import { View, Text, Image, TextInput } from 'react-native'; const App = () => { return ( <View> <Text>Hello, Welcome to React Native!</Text> <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={{ width: 50, height: 50 }} /> <TextInput placeholder="Type here..." /> </View> ); }; export default App;
React Native uses a StyleSheet to style components, similar to CSS but with camelCase properties.
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Text style={styles.text}>Styled Text in React Native</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, // Takes full height justifyContent: 'center', // Center vertically alignItems: 'center', // Center horizontally backgroundColor: '#f0f0f0', }, text: { fontSize: 20, fontWeight: 'bold', color: 'blue', }, }); export default App;
You can test your app on a real device or an emulator.
Android: Open Android Studio and start an emulator, then run:
npx react-native run-android
iOS: On a Mac, open Xcode and run:
npx react-native run-ios
Topic | Description |
---|---|
What is React Native? | A JavaScript framework for cross-platform mobile development. |
Setting up the Environment | Install Node.js, Expo CLI (recommended) or React Native CLI. |
Creating a React Native App | Initialize a project using expo init or npx react-native init. |
Understanding Components | Learn core components like View, Text, Image, TextInput. |
Styling Components | Use StyleSheet for applying styles. |
Running the App | Run on an emulator, iOS simulator, or real device. |
The View component is a container used for structuring UI elements, similar to <div> in web development.
<View style={styles.container}> {/* Child components go here */} </View>
import React from 'react'; import { View, Text } from 'react-native'; const App = () => { return ( <View> <Text>Hello, React Native!</Text> </View> ); }; export default App;
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Text style={styles.text}>Styled View</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f0f0f0', }, text: { fontSize: 18, color: 'blue', }, }); export default App;
import React from 'react'; import { View, Text } from 'react-native'; const App = () => { return ( <View> <View> <Text>Inside First View</Text> </View> <View> <Text>Inside Second View</Text> </View> </View> ); }; export default App;
import React from 'react'; import { View, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <View style={styles.box1} /> <View style={styles.box2} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', }, box1: { flex: 1, backgroundColor: 'red', }, box2: { flex: 1, backgroundColor: 'blue', }, }); export default App;
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.box}> <Text>Box with Border</Text> </View> ); }; const styles = StyleSheet.create({ box: { borderWidth: 2, borderColor: 'black', padding: 10, margin: 10, }, }); export default App;
The Text component is used for displaying text in React Native.
<Text style={styles.textStyle}>Hello, World!</Text>
import React from 'react'; import { Text } from 'react-native'; const App = () => { returnHello, React Native! ; }; export default App;
import React from 'react'; import { Text, StyleSheet } from 'react-native'; const App = () => { returnStyled Text ; }; const styles = StyleSheet.create({ text: { fontSize: 20, fontWeight: 'bold', color: 'blue', }, }); export default App;
import React from 'react'; import { Text } from 'react-native'; const App = () => { return (This is a long text that wraps across multiple lines in React Native. ); }; export default App;
import React from 'react'; import { Text, StyleSheet } from 'react-native'; const App = () => { returnCentered Text ; }; const styles = StyleSheet.create({ centerText: { textAlign: 'center', fontSize: 18, }, }); export default App;
import React from 'react'; import { Text, StyleSheet } from 'react-native'; const App = () => { return (); }; const styles = StyleSheet.create({ bold: { fontWeight: 'bold' }, italic: { fontStyle: 'italic' }, }); export default App; Bold Text andItalic Text .
The Image component is used to display images in React Native.
<Image source={{ uri: 'image_url' }} style={styles.image} />
import React from 'react';
import { Image } from 'react-native';
const App = () => {
return (
<Image
source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
style={{ width: 50, height: 50 }}
/>
);
export default App;
import React from 'react';
import { Image } from 'react-native';
const App = () => {
return <Image source={require('./assets/logo.png')} style={{ width: 100, height: 100 }} />
};
export default App;
import React from 'react';
import { Image, StyleSheet } from 'react-native';
const App = () => {
return <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={styles.image} />
};
const styles = StyleSheet.create({
image: {
width: 100,
height: 100,
borderRadius: 50,
},
});
export default App;
Handling user input is essential in mobile applications. React Native provides several ways to manage user interactions, such as buttons, text input fields, touch gestures, and lists. This chapter covers:
Each section will include fully commented code and 7 simple examples to reinforce understanding.
The Button component in React Native is used to create a simple pressable button with built-in styling.
<Button title="Click Me" onPress={myFunction} />
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
// Function to execute when button is pressed
const handlePress = () => {
alert('Button Pressed!');
};
return (
<View>
<Button title="Click Me" onPress={handlePress} />
</View>
);
};
export default App;
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
return (
<View>
<Button title="Submit" onPress={() => alert('Submitted!')} />
<Button title="Cancel" onPress={() => alert('Canceled!')} />
</View>
);
};
export default App;
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
return (
<View>
<Button title="Red Button" color="red" onPress={() => alert('Red Button Pressed!')} />
</View>
);
};
export default App;
import React from 'react';
import { View, Button, StyleSheet } from 'react-native';
const App = () => {
return (
<View style={styles.container}>
<Button title="Styled Button" onPress={() => alert('Button Pressed!')} />
</View>
);
};
const styles = StyleSheet.create({
container: {
margin: 20,
padding: 10,
backgroundColor: '#f0f0f0',
borderRadius: 10,
},
});
export default App;
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
return (
<View>
<Button title="Button 1" onPress={() => alert('Button 1 Pressed!')} />
<Button title="Button 2" onPress={() => alert('Button 2 Pressed!')} />
<Button title="Button 3" onPress={() => alert('Button 3 Pressed!')} />
</View>
);
};
export default App;
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
return (
<View>
<Button title="Disabled Button" disabled onPress={() => alert('Button Pressed!')} />
</View>
);
};
export default App;
import React from 'react';
import { View, Button } from 'react-native';
const App = () => {
const showMessage = (message) => {
alert(message);
};
return (
<View>
<Button title="Show Message" onPress={() => showMessage('Hello, React Native!')} />
</View>
);
};
export default App;
TouchableOpacity is a more customizable button that provides visual feedback when pressed.
<TouchableOpacity onPress={myFunction}>
<Text>Click Me</Text>
</TouchableOpacity>
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
const App = () => {
return (
<View>
<TouchableOpacity onPress={() => alert('Touchable Pressed!')}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
);
};
export default App;
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
const App = () => {
return (
<View>
<TouchableOpacity style={styles.button} onPress={() => alert('Styled Button Pressed!')}>
<Text style={styles.text}>Press Me</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
button: {
backgroundColor: 'blue',
padding: 10,
borderRadius: 5,
},
text: {
color: 'white',
textAlign: 'center',
},
});
export default App;
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
const App = () => {
return (
<View>
<TouchableOpacity style={styles.button} onPress={() => alert('Button Pressed!')}>
<Text style={styles.text}>Bordered Button</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
button: {
borderWidth: 2,
borderColor: 'black',
padding: 10,
margin: 10,
borderRadius: 5,
},
text: {
textAlign: 'center',
},
});
export default App;
import React from 'react';
import { View, Image, TouchableOpacity } from 'react-native';
const App = () => {
return (
<View>
<TouchableOpacity onPress={() => alert('Image Pressed!')}>
<Image
source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
style={{ width: 50, height: 50 }}
/>
</TouchableOpacity>
</View>
);
};
export default App;
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
const App = () => {
const handlePress = () => {
alert('You Pressed the Button!');
console.log('Button Pressed');
};
return (
<View>
<TouchableOpacity onPress={handlePress}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
);
};
export default App;
The TextInput component is used to receive user input in a text field. It supports various properties like placeholder, secureTextEntry (for passwords), keyboardType, and onChangeText (to handle input changes).
<TextInput
placeholder="Enter text"
onChangeText={handleInput}
/>
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [text, setText] = useState('');
return (
<View>
<TextInput
placeholder="Type here..."
onChangeText={setText} // Updates state when text changes
style={{ borderWidth: 1, padding: 10 }}
/>
<Text>You typed: {text}</Text>
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
const App = () => {
const [text, setText] = useState('');
return (
<View>
<TextInput
style={styles.input}
placeholder="Enter your name"
onChangeText={setText}
/>
<Text>Hello, {text}!</Text>
</View>
);
};
const styles = StyleSheet.create({
input: {
borderWidth: 1,
borderColor: 'gray',
padding: 10,
borderRadius: 5,
margin: 10,
},
});
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [password, setPassword] = useState('');
return (
<View>
<TextInput
placeholder="Enter Password"
secureTextEntry={true} // Hides input text
onChangeText={setPassword}
style={{ borderWidth: 1, padding: 10 }}
/>
<Text>Entered Password: {password}</Text>
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [number, setNumber] = useState('');
return (
<View>
<TextInput
placeholder="Enter a number"
keyboardType="numeric" // Sets numeric keyboard
onChangeText={setNumber}
style={{ borderWidth: 1, padding: 10 }}
/>
<Text>Number: {number}</Text>
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [message, setMessage] = useState('');
return (
<View>
<TextInput
placeholder="Enter your message"
multiline={true} // Allows multiple lines
numberOfLines={4} // Sets height
onChangeText={setMessage}
style={{ borderWidth: 1, padding: 10, height: 100 }}
/>
<Text>Message: {message}</Text>
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [text, setText] = useState('');
return (
<View>
<TextInput
placeholder="Enter max 10 chars"
maxLength={10} // Limits characters to 10
onChangeText={setText}
style={{ borderWidth: 1, padding: 10 }}
/>
<Text>Input: {text}</Text>
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
const App = () => {
const [text, setText] = useState('');
return (
<View>
<TextInput
placeholder="Type here..."
autoCapitalize="words" // Capitalizes each word
onChangeText={setText}
style={{ borderWidth: 1, padding: 10 }}
/>
<Text>You typed: {text}</Text>
</View>
);
};
export default App;
It's often used when the content exceeds the size of the screen. You can have a vertical or horizontal scroll, and it supports various properties like onEndReached
to handle when the user reaches the end of the list.
<ScrollView> <YourContentHere /> </ScrollView>
import React from 'react'; import { View, Text, ScrollView } from 'react-native'; const App = () => { return ( <ScrollView> <Text>Item 1</Text> <Text>Item 2</Text> <Text>Item 3</Text> <Text>Item 4</Text> <Text>Item 5</Text> <Text>Item 6</Text> <Text>Item 7</Text> </ScrollView> ); }; export default App;
import React from 'react'; import { View, Text, ScrollView } from 'react-native'; const App = () => { return ( <ScrollView horizontal={true}> <Text style={{ margin: 10 }}>Item 1</Text> <Text style={{ margin: 10 }}>Item 2</Text> <Text style={{ margin: 10 }}>Item 3</Text> <Text style={{ margin: 10 }}>Item 4</Text> <Text style={{ margin: 10 }}>Item 5</Text> </ScrollView> ); }; export default App;
import React from 'react'; import { ScrollView, Text } from 'react-native'; const App = () => { return ( <ScrollView> <Text>Vertical ScrollView</Text> <ScrollView horizontal={true}> <Text style={{ margin: 10 }}>Horizontal Item 1</Text> <Text style={{ margin: 10 }}>Horizontal Item 2</Text> </ScrollView> <Text>More Content</Text> </ScrollView> ); }; export default App;
import React from 'react'; import { View, Text, ScrollView, StyleSheet } from 'react-native'; const App = () => { return ( <ScrollView style={styles.scrollView}> <Text style={styles.text}>Item 1</Text> <Text style={styles.text}>Item 2</Text> <Text style={styles.text}>Item 3</Text> </ScrollView> ); }; const styles = StyleSheet.create({ scrollView: { padding: 20, backgroundColor: '#f0f0f0', }, text: { fontSize: 20, marginBottom: 10, }, }); export default App;
import React from 'react'; import { ScrollView, Image } from 'react-native'; const App = () => { return ( <ScrollView> <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={{ width: 200, height: 200, marginBottom: 20 }} /> <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={{ width: 200, height: 200 }} /> </ScrollView> ); }; export default App;
import React, { useState } from 'react'; import { View, Button, ScrollView, Text } from 'react-native'; const App = () => { const [items, setItems] = useState(['Item 1', 'Item 2']); const addItem = () => { setItems([...items, `Item ${items.length + 1}`]); }; return ( <View> <Button title="Add Item" onPress={addItem} /> <ScrollView> {items.map((item, index) => ( <Text key={index}>{item}</Text> ))} </ScrollView> </View> ); }; export default App;
import React, { useState } from 'react'; import { ScrollView, Text } from 'react-native'; const App = () => { const [endReached, setEndReached] = useState(false); return ( <ScrollView onEndReached={() => setEndReached(true)} onEndReachedThreshold={0.1} > <Text>Scroll to the end of this list</Text> {endReached && <Text>You have reached the end!</Text>} </ScrollView> ); }; export default App;
The FlatList component is used for rendering a list of data. It is optimized for displaying large lists with better performance than using ScrollView for the same purpose. FlatList only renders the items that are currently visible on the screen, improving memory usage.
<FlatList
data={yourDataArray}
renderItem={({ item }) => <YourComponent />}
keyExtractor={(item, index) => index.toString()}
/>
import React from 'react';
import { FlatList, Text } from 'react-native';
const App = () => {
const data = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
keyExtractor={(item, index) => index.toString()}
/>
);
};
export default App;
import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
const App = () => {
const data = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
return (
<FlatList
data={data}
renderItem={({ item }) => (
<View style={styles.item}>
<Text style={styles.text}>{item}</Text>
</View>
)}
keyExtractor={(item, index) => index.toString()}
/>
);
};
const styles = StyleSheet.create({
item: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#ddd',
},
text: {
fontSize: 18,
},
});
export default App;
import React from 'react';
import { FlatList, Image, Text, View, StyleSheet } from 'react-native';
const App = () => {
const data = [
{ id: '1', image: 'https://reactnative.dev/img/tiny_logo.png' },
{ id: '2', image: 'https://reactnative.dev/img/tiny_logo.png' },
];
return (
<FlatList
data={data}
renderItem={({ item }) => (
<View style={styles.item}>
<Image source={{ uri: item.image }} style={styles.image} />
<Text style={styles.text}>Item {item.id}</Text>
</View>
)}
keyExtractor={(item) => item.id}
/>
);
};
const styles = StyleSheet.create({
item: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#ddd',
},
image: {
width: 50,
height: 50,
marginBottom: 5,
},
text: {
fontSize: 18,
},
});
export default App;
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const App = () => {
const data = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
return (
<FlatList
data={data}
horizontal={true} // Enables horizontal scroll
renderItem={({ item }) => (
<View style={{ margin: 10 }}>
<Text>{item}</Text>
</View>
)}
keyExtractor={(item, index) => index.toString()}
/>
);
};
export default App;
import React, { useState } from 'react';
import { FlatList, Text, View, RefreshControl } from 'react-native';
const App = () => {
const [refreshing, setRefreshing] = useState(false);
const [data, setData] = useState(['Item 1', 'Item 2', 'Item 3']);
const onRefresh = () => {
setRefreshing(true);
setTimeout(() => {
setData([...data, `Item ${data.length + 1}`]);
setRefreshing(false);
}, 2000);
};
return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
keyExtractor={(item, index) => index.toString()}
refreshControl=<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
/>
);
};
export default App;
import React from 'react';
import { FlatList, Text, View, StyleSheet } from 'react-native';
const App = () => {
const data = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
return (
<FlatList
data={data}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
keyExtractor={(item, index) => index.toString()}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
};
const styles = StyleSheet.create({
item: {
padding: 10,
fontSize: 18,
},
separator: {
height: 1,
backgroundColor: '#ddd',
},
});
export default App;
import React, { useState } from 'react';
import { FlatList, Text, View } from 'react-native';
const App = () => {
const [data, setData] = useState(['Item 1', 'Item 2', 'Item 3']);
const [loading, setLoading] = useState(false);
const loadMoreData = () => {
if (!loading) {
setLoading(true);
setTimeout(() => {
setData([...data, `Item ${data.length + 1}`, `Item ${data.length + 2}`]);
setLoading(false);
}, 2000);
}
};
return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
keyExtractor={(item, index) => index.toString()}
onEndReached={loadMoreData}
onEndReachedThreshold={0.1} // Load more when scrolled near end
/>
);
};
export default App;
SectionList is ideal for displaying grouped data in sections with headers. Customize sections using renderSectionHeader, renderItem, and renderSectionFooter. You can use horizontal={true} for horizontal sections, and refreshControl for pull-to-refresh functionality. Sections can be dynamic, allowing for changes in content with state management.
<SectionList
sections={yourSectionsArray}
renderItem={({ item }) => <YourComponent />}
renderSectionHeader={({ section }) => <YourHeaderComponent />}
keyExtractor={(item, index) => index.toString()}
/>
import React from 'react'; import { SectionList, Text } from 'react-native'; const App = () => { const sections = [ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]; return ({item} } renderSectionHeader={({ section }) =>{section.title} } keyExtractor={(item, index) => index.toString()} /> ); }; export default App;
import React from 'react'; import { SectionList, Text, StyleSheet } from 'react-native'; const App = () => { const sections = [ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]; return ({item} } renderSectionHeader={({ section }) => ({section.title} )} keyExtractor={(item, index) => index.toString()} /> ); }; const styles = StyleSheet.create({ item: { fontSize: 18, padding: 10, }, header: { fontSize: 22, fontWeight: 'bold', backgroundColor: '#ddd', padding: 5, }, }); export default App;
import React from 'react'; import { SectionList, Text, StyleSheet } from 'react-native'; const App = () => { const sections = [ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]; return ({item} } renderSectionHeader={({ section }) => ({section.title} )} keyExtractor={(item, index) => index.toString()} /> ); }; const styles = StyleSheet.create({ item: { fontSize: 18, padding: 10, backgroundColor: '#f9f9f9', borderBottomWidth: 1, borderBottomColor: '#ddd', }, header: { fontSize: 22, fontWeight: 'bold', backgroundColor: '#ddd', padding: 5, }, }); export default App;
import React from 'react'; import { SectionList, Text, View, StyleSheet } from 'react-native'; const App = () => { const sections = [ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'], footer: 'More fruits to come!' }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'], footer: 'Fresh veggies daily!' }, ]; return ({item} } renderSectionHeader={({ section }) => ({section.title} )} renderSectionFooter={({ section }) => ({section.footer} )} keyExtractor={(item, index) => index.toString()} /> ); }; const styles = StyleSheet.create({ item: { fontSize: 18, padding: 10, backgroundColor: '#f9f9f9', borderBottomWidth: 1, borderBottomColor: '#ddd', }, header: { fontSize: 22, fontWeight: 'bold', backgroundColor: '#ddd', padding: 5, }, footer: { fontSize: 16, fontStyle: 'italic', backgroundColor: '#f0f0f0', padding: 5, }, }); export default App;
import React from 'react'; import { SectionList, Text, View, StyleSheet } from 'react-native'; const App = () => { const sections = [ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]; return (( <View style={styles.item}> <Text>{item}</Text> </View> )} renderSectionHeader={({ section }) => ( {section.title} )} keyExtractor={(item, index) => index.toString()} /> ); }; const styles = StyleSheet.create({ item: { fontSize: 18, margin: 10, padding: 10, backgroundColor: '#ddd', }, header: { fontSize: 22, fontWeight: 'bold', backgroundColor: '#ddd', padding: 5, }, }); export default App;
import React, { useState } from 'react'; import { SectionList, Text, View, RefreshControl } from 'react-native'; const App = () => { const [refreshing, setRefreshing] = useState(false); const [sections, setSections] = useState([ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]); const onRefresh = () => { setRefreshing(true); setTimeout(() => { setSections([ ...sections, { title: 'New Section', data: ['Mango', 'Pineapple'] }, ]); setRefreshing(false); }, 2000); }; return ({item} } renderSectionHeader={({ section }) =>{section.title} } refreshControl={} keyExtractor={(item, index) => index.toString()} /> ); }; export default App;
import React, { useState } from 'react'; import { SectionList, Text, Button, View } from 'react-native'; const App = () => { const [sections, setSections] = useState([ { title: 'Fruits', data: ['Apple', 'Banana', 'Cherry'] }, { title: 'Vegetables', data: ['Carrot', 'Lettuce', 'Spinach'] }, ]); const addSection = () => { setSections([ ...sections, { title: 'Berries', data: ['Strawberry', 'Blueberry', 'Raspberry'] }, ]); }; return ( <View> <Button title="Add Section" onPress={addSection} /> <SectionList sections={sections} renderItem={({ item }) => <Text>{item}</Text>} renderSectionHeader={({ section }) => <Text>{section.title}</Text>} keyExtractor={(item, index) => index.toString()} /> </View> ); }; export default App;
Keyboard handling in React Native is essential for managing how the keyboard interacts with the screen when the user focuses on input fields. The most commonly used components and APIs for keyboard handling are KeyboardAvoidingView
, TouchableWithoutFeedback
, Keyboard.dismiss()
, and TextInput
.
import { KeyboardAvoidingView, TextInput, TouchableWithoutFeedback, Keyboard } from 'react-native';
<KeyboardAvoidingView behavior="padding" style={styles.container}>
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View>
<TextInput placeholder="Type here" />
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
import React from 'react';
import { KeyboardAvoidingView, TextInput, StyleSheet, Platform } from 'react-native';
const App = () => {
return (
<KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<TextInput placeholder="Type here" style={styles.input} />
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
margin: 10,
paddingLeft: 10,
},
});
export default App;
import React from 'react';
import { View, TextInput, TouchableWithoutFeedback, Keyboard, StyleSheet } from 'react-native';
const App = () => {
return (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View style={styles.container}>
<TextInput placeholder="Tap outside to dismiss keyboard" style={styles.input} />
</View>
</TouchableWithoutFeedback>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
marginBottom: 20,
paddingLeft: 10,
},
});
export default App;
import React from 'react';
import { KeyboardAvoidingView, TextInput, StyleSheet, Platform } from 'react-native';
const App = () => {
return (
<KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<TextInput placeholder="First Name" style={styles.input} />
<TextInput placeholder="Last Name" style={styles.input} />
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
margin: 10,
paddingLeft: 10,
},
});
export default App;
import React from 'react';
import { View, TextInput, Button, StyleSheet, Keyboard } from 'react-native';
const App = () => {
const handleSubmit = () => {
Keyboard.dismiss();
console.log('Form submitted');
};
return (
<View style={styles.container}>
<TextInput placeholder="Type here" style={styles.input} />
<Button title="Submit" onPress={handleSubmit} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
marginBottom: 20,
paddingLeft: 10,
},
});
export default App;
import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet, Keyboard } from 'react-native';
const App = () => {
const [text, setText] = useState('');
const handleFocus = () => {
console.log('TextInput focused');
};
return (
<View style={styles.container}>
<TextInput
value={text}
onChangeText={setText}
placeholder="Type here"
style={styles.input}
onFocus={handleFocus}
/>
<Button title="Dismiss Keyboard" onPress={() => Keyboard.dismiss()} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
marginBottom: 20,
paddingLeft: 10,
},
});
export default App;
import React from 'react';
import { KeyboardAvoidingView, ScrollView, TextInput, Button, StyleSheet, Platform } from 'react-native';
const App = () => {
return (
<KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<ScrollView contentContainerStyle={styles.scrollContainer}>
<TextInput placeholder="Type here" style={styles.input} />
<TextInput placeholder="Type more" style={styles.input} />
<Button title="Submit" onPress={() => console.log('Form submitted')} />
</ScrollView>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContainer: {
flexGrow: 1,
justifyContent: 'center',
padding: 20,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
marginBottom: 20,
paddingLeft: 10,
},
});
export default App;
import React, { useState } from 'react';
import { KeyboardAvoidingView, TextInput, Button, StyleSheet, Platform, Keyboard } from 'react-native';
const App = () => {
const [formData, setFormData] = useState({ name: '', email: '' });
const handleInputChange = (field, value) => {
setFormData({
...formData,
[field]: value,
});
};
const handleSubmit = () => {
Keyboard.dismiss();
console.log('Form Submitted:', formData);
};
return (
<KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<TextInput
placeholder="Name"
style={styles.input}
value={formData.name}
onChangeText={(text) => handleInputChange('name', text)}
/>
<TextInput
placeholder="Email"
style={styles.input}
value={formData.email}
onChangeText={(text) => handleInputChange('email', text)}
/>
<Button title="Submit" onPress={handleSubmit} />
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
input: {
height: 40,
borderColor: '#ccc',
borderWidth: 1,
marginBottom: 20,
paddingLeft: 10,
},
});
export default App;
This concludes the examples for Keyboard Handling in React Native. These examples cover the basics of using KeyboardAvoidingView, dismissing the keyboard, handling multiple inputs, and ensuring the keyboard behaves appropriately on different devices.
In React Native, managing data between components is done using props and state. Props are used to pass data between components, while state is used to manage data within a component. In this chapter, we'll go over these concepts and show examples using simple code snippets.
In React and React Native, Hooks are special functions that allow you to "hook into" React's state and lifecycle features from function components. They were introduced in React 16.8 to allow function components to have features that were previously only available in class components, such as managing state, side effects, and context.
The useState
hook allows you to add state to a function component. It returns an array with two elements:
const [state, setState] = useState(initialValue);
state: The current state value.
setState: A function used to update the state.
initialValue: The initial value you want to set for the state.
import React, { useState } from 'react';
import { Text, Button, View } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0); // Declare state 'count' with initial value 0
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
export default Counter;
In this example:
count
state variable and initialize it with a value of 0.setCount
function updates the state, causing the component to re-render with the new count value.In React and React Native, State refers to the data or values that can change during the lifecycle of a component. Unlike props, which are passed from parent to child and are immutable, state is local to a component and can be modified by that component. State allows components to maintain dynamic, interactive behavior.
State is typically used to track things like:
In function components, state is managed using the useState
hook, while in class components, state is managed using the this.state
object and this.setState()
method.
import React, { Component } from 'react';
import { Text, Button, View } from 'react-native';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 }; // Initial state
}
increment = () => {
this.setState({ count: this.state.count + 1 }); // Updating state
};
render() {
return (
<View>
<Text>Count: {this.state.count}</Text>
<Button title="Increment" onPress={this.increment} />
</View>
);
}
}
export default Counter;
useState
allow function components to use state and other React features.Props are used to pass data from a parent component to a child component. Props are read-only, meaning they can't be modified by the child component, but they can be used to render dynamic content.
const ParentComponent = () => { return; }; const ChildComponent = (props) => { return ( Name: {props.name}, Age: {props.age} ); };
import React from 'react'; import { Text, View } from 'react-native'; const ParentComponent = () => { return; }; const ChildComponent = (props) => { return ( <View> <Text>Name: {props.name}</Text> <Text>Age: {props.age}</Text> </View> ); }; export default ParentComponent;
Explanation: Here, the ParentComponent passes the name and age as props to the ChildComponent, which then displays them in a Text element.
State is used to manage data that can change over time within a component. Unlike props, state is mutable and can be changed using the useState
hook.
import React, { useState } from 'react';
import { View, Text } from 'react-native';
const App = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
export default App;
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
<Button title="Decrement" onPress={() => setCount(count - 1)} />
</View>
);
};
export default App;
Explanation: This example shows how to use the useState hook to create a count state variable and update it using setCount. The Button components allow the user to increment or decrement the count.
<TextInput
value={this.state.input}
onChangeText={(text) => this.setState({ input: text })}
placeholder="Type something..."
/>
<Text>You typed: {this.state.input}</Text>
<Button
title="Change Text"
onPress={() => this.setState({ text: "Hello, World!" })}
/>
<Text>{this.state.text}</Text>
<Button
title="Increment Counter"
onPress={() => this.setState({ count: this.state.count + 1 })}
/>
<Text>Counter: {this.state.count}</Text>
<Button
title="Change Name"
onPress={() => this.setState({ name: "John" })}
/>
<Text>Name: {this.state.name}</Text>
This section demonstrates how to handle user interactions in React Native, including button clicks, gestures, and text input changes.
This example shows how to handle a button click using the onPress
event in React Native.
{` import React, { useState } from 'react'; import { View, Button, Text } from 'react-native'; // Function component to handle button click const ButtonClickExample = () => { // State to track button clicks const [count, setCount] = useState(0); // Function to increment count when button is pressed const handleButtonPress = () => { setCount(count + 1); // Update count by 1 on every button press }; return ( <View style={{ padding: 20 }}> <Button title="Click Me!" onPress={handleButtonPress} /> {/* Button that triggers handleButtonPress */} <Text>You clicked {count} times</Text> {/* Display the number of clicks */} </View> ); }; export default ButtonClickExample; `}
This example demonstrates how to use TouchableOpacity
to create custom buttons in React Native.
{` import React, { useState } from 'react'; import { View, TouchableOpacity, Text } from 'react-native'; // Function component to handle custom button click const TouchableOpacityExample = () => { const [message, setMessage] = useState('Hello, World!'); // Function to change message when button is pressed const handleChangeMessage = () => { setMessage('You pressed the button!'); }; return ( <View style={{ padding: 20 }}> <TouchableOpacity style={{ backgroundColor: '#007BFF', padding: 10, borderRadius: 5, }} onPress={handleChangeMessage} // Trigger message change on press > <Text style={{ color: 'white', textAlign: 'center' }}>Press Me!</Text> </TouchableOpacity> <Text>{message}</Text> {/* Display updated message */} </View> ); }; export default TouchableOpacityExample; `}
This example shows how to change text dynamically when a user interacts with a text input.
{` import React, { useState } from 'react'; import { View, TextInput, Text } from 'react-native'; // Function component to handle dynamic text change const TextInputExample = () => { // State to store text input value const [text, setText] = useState(''); return ( <View style={{ padding: 20 }}> <TextInput style={{ height: 40, borderColor: 'gray', borderWidth: 1, marginBottom: 20, paddingLeft: 8, }} placeholder="Type something..." onChangeText={setText} // Update state with input text value={text} // Bind text input to state value /> <Text>You typed: {text}</Text> {/* Dynamically display text entered */} </View> ); }; export default TextInputExample; `}
This example demonstrates how to use PanResponder
to track and respond to gestures such as dragging.
{` import React, { useState } from 'react'; import { View, Text, PanResponder } from 'react-native'; const PanResponderExample = () => { // State to track position of the pan gesture const [position, setPosition] = useState({ x: 0, y: 0 }); // PanResponder to track drag gesture const panResponder = PanResponder.create({ onMoveShouldSetPanResponder: () => true, // Enable responder for move gestures onPanResponderMove: (event, gestureState) => { // Update position while dragging setPosition({ x: gestureState.moveX, y: gestureState.moveY, }); }, onPanResponderRelease: () => { // Reset position when gesture ends setPosition({ x: 0, y: 0 }); }, }); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <View {...panResponder.panHandlers} // Attach pan responder handlers style={{ width: 100, height: 100, backgroundColor: '#007BFF', position: 'absolute', top: position.y - 50, // Offset to center the box left: position.x - 50, // Offset to center the box }} /> <Text>Move the blue box around!</Text> </View> ); }; export default PanResponderExample; `}
This example demonstrates how to handle a long press gesture using TouchableWithoutFeedback
in React Native.
{` import React from 'react'; import { View, Text, TouchableWithoutFeedback } from 'react-native'; const LongPressExample = () => { // Function to handle long press gesture const handleLongPress = () => { alert('Long Press Detected!'); // Show an alert on long press }; return ( <View style={{ padding: 20 }}> <TouchableWithoutFeedback onLongPress={handleLongPress}> {/* Detect long press */} <View style={{ width: 200, height: 100, backgroundColor: '#28a745', justifyContent: 'center', alignItems: 'center', borderRadius: 10, }}> <Text style={{ color: 'white' }}>Long Press Me!</Text> </View> </TouchableWithoutFeedback> </View> ); }; export default LongPressExample; `}
This example shows how to set up navigation in a React Native app using react-navigation:
<import { NavigationContainer } from '@react-navigation/native' /> <import { createStackNavigator } from '@react-navigation/stack' /> <const Stack = createStackNavigator() /> <function App() {> <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> </NavigationContainer> <}>
In this example, we navigate between two screens:
<function HomeScreen({ navigation }) {> return ( <View> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> ) <}>
This example shows how to pass data from one screen to another:
<function HomeScreen({ navigation }) {> return ( <View> <Button title="Go to Details" onPress={() => navigation.navigate('Details', { itemId: 86 })} /> </View> ) <}> <function DetailsScreen({ route }) {> const { itemId } = route.params; return <Text>Item ID: {itemId}</Text> <}>
This example demonstrates creating a bottom tab navigation:
<import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' /> <const Tab = createBottomTabNavigator() /> <function App() {> return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> ) <}>
This example demonstrates creating a drawer navigation:
<import { createDrawerNavigator } from '@react-navigation/drawer' /> <const Drawer = createDrawerNavigator() /> <function App() {> return ( <NavigationContainer> <Drawer.Navigator> <Drawer.Screen name="Home" component={HomeScreen} /> <Drawer.Screen name="Profile" component={ProfileScreen} /> </Drawer.Navigator> </NavigationContainer> ) <}>
The fetch
API is a built-in JavaScript method for making HTTP requests. It is used to get data from external resources (APIs).
Example of using fetch
to get data from a public API:
// Fetching data from a public API
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json()) // Convert response to JSON
.then(data => {
console.log(data); // Log the data to the console
})
.catch(error => console.error('Error fetching data:', error)); // Handle errors
This code fetches a list of posts from a placeholder API and logs the data to the console. The then
method handles the response, and catch
handles any errors.
axios
is a popular JavaScript library for making HTTP requests. It simplifies requests and provides additional features over fetch
.
Example of using axios
to fetch data:
// Using axios to fetch data
axios.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
console.log(response.data); // Log the data to the console
})
.catch(error => console.error('Error fetching data with axios:', error)); // Handle errors
This code is similar to the fetch example but uses the axios.get
method to fetch data. axios
automatically parses the response to JSON.
Once the data is fetched from an API, you can display it in an HTML list. Below is an example of displaying fetched posts in an unordered list:
// Fetching data and displaying it in a list
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
const list = document.getElementById('post-list');
data.forEach(post => {
const li = document.createElement('li');
li.textContent = post.title; // Add title to the list item
list.appendChild(li); // Append the item to the list
});
})
.catch(error => console.error('Error fetching data:', error));
In the above example, the data from the API is looped through, and each post's title is added as an item to an unordered list on the page.
Handling errors is essential when working with API requests. You can catch errors like network issues or invalid responses using catch
.
Example of handling errors in a fetch
request:
fetch('https://jsonplaceholder.typicode.com/invalid-url') // Invalid URL to trigger error
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok'); // Throw error if response is not OK
}
return response.json(); // Convert response to JSON
})
.then(data => console.log(data))
.catch(error => {
console.error('There was a problem with the fetch operation:', error); // Handle the error
});
This example shows how to handle errors by checking the response status and using catch
to log errors when something goes wrong.
The async/await
syntax makes working with promises easier and cleaner. Below is an example of fetching data using async/await
:
// Using async/await to fetch data
async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data); // Log the data to the console
} catch (error) {
console.error('Error fetching data:', error); // Handle errors
}
}
fetchData(); // Call the function to fetch data
In this example, the fetchData
function uses await
to wait for the API response, and try/catch
is used to handle errors.
The Animated
API in React Native allows us to create smooth animations. Below is an example of creating a fade-in effect:
// Import the Animated API from React Native
import { Animated } from 'react-native';
import React, { useState, useEffect } from 'react';
const FadeInExample = () => {
const fadeAnim = useState(new Animated.Value(0))[0]; // Initialize fade animation with 0 (fully transparent)
useEffect(() => {
// Trigger the fade-in animation after the component mounts
Animated.timing(fadeAnim, {
toValue: 1, // Fade to fully opaque
duration: 2000, // Duration of 2 seconds
useNativeDriver: true, // Use native driver for better performance
}).start(); // Start the animation
}, []);
return (
<Animated.View style={{ ...styles.fadeContainer, opacity: fadeAnim }}>
<Text>Fade-In Animation</Text>
</Animated.View>
);
};
const styles = {
fadeContainer: {
alignItems: 'center',
justifyContent: 'center',
padding: 20,
backgroundColor: '#f5f5f5',
},
};
export default FadeInExample;
This code demonstrates how to create a fade-in effect where an element fades in from being fully transparent to fully visible.
This example shows how to create a bounce animation using the Animated.spring()
method:
import { Animated } from 'react-native';
import React, { useState, useEffect } from 'react';
const BounceExample = () => {
const bounceAnim = useState(new Animated.Value(1))[0]; // Initial scale of 1
useEffect(() => {
// Trigger the bounce animation when the component mounts
Animated.spring(bounceAnim, {
toValue: 1.5, // Scale the element to 1.5 times its original size
friction: 2, // Adjust the "bounciness"
tension: 150, // Adjust the speed of the bounce
useNativeDriver: true, // Use native driver for performance
}).start(); // Start the animation
}, []);
return (
<Animated.View style={{ ...styles.bounceContainer, transform: [{ scale: bounceAnim }] }}>
<Text>Bounce Animation</Text>
</Animated.View>
);
};
const styles = {
bounceContainer: {
alignItems: 'center',
justifyContent: 'center',
padding: 20,
backgroundColor: '#f5f5f5',
},
};
export default BounceExample;
This example shows how to create a bounce effect where the element scales up and then springs back down using Animated.spring()
.
Below is an example of moving an object across the screen using Animated.timing()
:
import { Animated } from 'react-native';
import React, { useState, useEffect } from 'react';
const MoveExample = () => {
const moveAnim = useState(new Animated.Value(0))[0]; // Starting position
useEffect(() => {
// Trigger the move animation
Animated.timing(moveAnim, {
toValue: 300, // Move the object 300 units to the right
duration: 2000, // Duration of the animation
useNativeDriver: true,
}).start(); // Start the animation
}, []);
return (
<Animated.View style={{ ...styles.moveContainer, transform: [{ translateX: moveAnim }] }}>
<Text>Move Animation</Text>
</Animated.View>
);
};
const styles = {
moveContainer: {
alignItems: 'center',
justifyContent: 'center',
padding: 20,
backgroundColor: '#f5f5f5',
},
};
export default MoveExample;
This code moves an element across the screen from left to right, using translateX
transformation to animate its position.
This example demonstrates how to scale an image dynamically using Animated.Value
and transform
:
import { Animated, Image } from 'react-native';
import React, { useState, useEffect } from 'react';
const ScaleImageExample = () => {
const scaleAnim = useState(new Animated.Value(1))[0]; // Initial scale of 1 (original size)
useEffect(() => {
// Trigger the scaling animation
Animated.timing(scaleAnim, {
toValue: 2, // Scale the image to double its size
duration: 2000, // Duration of the animation
useNativeDriver: true,
}).start(); // Start the animation
}, []);
return (
<Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
<Image source={{ uri: 'https://placekitten.com/200/300' }} style={{ width: 200, height: 300 }} />
</Animated.View>
);
};
export default ScaleImageExample;
This code demonstrates how to scale an image, dynamically changing its size from the original to twice its size during the animation.
LayoutAnimation
provides automatic layout transitions. Below is an example:
import { LayoutAnimation, View, Button, Text } from 'react-native';
import React, { useState } from 'react';
const LayoutAnimationExample = () => {
const [toggle, setToggle] = useState(false);
const handleToggle = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); // Smooth transition
setToggle(!toggle); // Toggle the value
};
return (
<View>
<Button title="Toggle View" onPress={handleToggle} />
<View style={{ height: toggle ? 100 : 50, backgroundColor: '#f5f5f5', marginTop: 20 }}>
<Text>Resize Me!</Text>
</View>
</View>
);
};
export default LayoutAnimationExample;
This example demonstrates using LayoutAnimation
to create smooth transitions when a view’s layout changes, such as when its height toggles between two values.
Below is an example of using the Context API
to manage theme settings in an app:
import React, { createContext, useState, useContext } from 'react';
import { View, Text, Button } from 'react-native';
const ThemeContext = createContext(); // Create the context
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
const ThemedComponent = () => {
const { theme, toggleTheme } = useContext(ThemeContext); // Use the context
return (
<View style={{ backgroundColor: theme === 'light' ? '#fff' : '#333', flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ color: theme === 'light' ? '#000' : '#fff' }}>Current theme: {theme}</Text>
<Button title="Toggle Theme" onPress={toggleTheme} />
</View>
);
};
const App = () => (
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
export default App;
This code shows how to toggle between light and dark themes using the Context API, providing a shared state to the components.
Here’s how to set up Redux to manage the global state:
// actions.js
export const setUser = (user) => ({
type: 'SET_USER',
payload: user,
});
// reducer.js
const initialState = { user: null };
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload };
default:
return state;
}
};
export default userReducer;
// App.js
import React from 'react';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { createStore } from 'redux';
import userReducer from './reducer';
const store = createStore(userReducer); // Create the Redux store
const App = () => {
const dispatch = useDispatch();
const user = useSelector(state => state.user); // Get the user from the state
const handleSetUser = () => {
dispatch({ type: 'SET_USER', payload: { name: 'John Doe' } });
};
return (
<View>
<Text>User: {user ? user.name : 'No user set'}</Text>
<Button title="Set User" onPress={handleSetUser} />
</View>
);
};
export default () => (
<Provider store={store}>
<App />
</Provider>
);
This example demonstrates how to set up Redux by creating actions, reducers, and the Redux store. It shows how to manage a user object in the global state.
This example shows how to fetch data from an API and store it in Redux:
import { createStore } from 'redux';
import { Provider, useDispatch, useSelector } from 'react-redux';
import React, { useEffect } from 'react';
import { View, Text, Button } from 'react-native';
const FETCH_DATA = 'FETCH_DATA';
const fetchData = (data) => ({
type: FETCH_DATA,
payload: data,
});
const dataReducer = (state = { data: [] }, action) => {
switch (action.type) {
case FETCH_DATA:
return { ...state, data: action.payload };
default:
return state;
}
};
const store = createStore(dataReducer); // Create Redux store
const FetchDataComponent = () => {
const dispatch = useDispatch();
const data = useSelector(state => state.data);
useEffect(() => {
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => dispatch(fetchData(data))); // Store the data in Redux
}, [dispatch]);
return (
<View>
<Text>Fetched Data:</Text>
{data.map((item, index) => (
<Text key={index}>{item.name}</Text>
))}
</View>
);
};
export default () => (
<Provider store={store}>
<FetchDataComponent />
</Provider>
);
This code demonstrates how to fetch data from an API and store it in Redux, allowing the component to access the data globally.
Zustand is a lightweight state management tool that can be used as an alternative to Redux. Here’s an example:
import create from 'zustand';
// Creating a store with Zustand
const useStore = create((set) => ({
theme: 'light',
toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
}));
const App = () => {
const { theme, toggleTheme } = useStore(); // Access the global state
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: theme === 'light' ? '#fff' : '#333' }}>
<Text style={{ color: theme === 'light' ? '#000' : '#fff' }}>Current theme: {theme}</Text>
<Button title="Toggle Theme" onPress={toggleTheme} />
</View>
);
};
export default App;
Zustand makes state management easy and simple, as seen here, where we use useStore
to manage the theme state with a simple API.
In this example, we show how to persist state using AsyncStorage
:
import { AsyncStorage } from 'react-native';
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [name, setName] = useState('');
useEffect(() => {
// Fetch the persisted name from AsyncStorage
AsyncStorage.getItem('name').then((storedName) => {
if (storedName) {
setName(storedName);
}
});
}, []);
const handleSave = () => {
// Persist the name to AsyncStorage
AsyncStorage.setItem('name', name);
};
return (
<View>
<Text>Saved Name: {name}</Text>
<Button title="Save Name" onPress={handleSave} />
</View>
);
};
export default App;
This example demonstrates how to use AsyncStorage
to persist data, allowing it to persist across app reloads.
Using AsyncStorage: AsyncStorage is a simple, unencrypted, persistent key-value store that is global to the app. It allows storing and retrieving data persistently between app sessions. It is useful for storing small data such as user preferences, app settings, or other basic information.
Saving user preferences: Saving user preferences can be done using AsyncStorage. For example, you can save the user's theme settings, language, or even the last visited screen. This allows the app to maintain the user's choices across app launches.
Retrieving and clearing data: You can retrieve the saved data from AsyncStorage using its getItem()
method. You can also clear or remove data with the removeItem()
method, which is useful when you want to delete user preferences or other stored data.
Here’s how you can save a string in AsyncStorage
:
import { AsyncStorage } from 'react-native';
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [name, setName] = useState('');
const handleSave = () => {
// Save the name string to AsyncStorage
AsyncStorage.setItem('userName', name);
};
return (
<View>
<Text>Enter your name:</Text>
<TextInput
placeholder="Name"
value={name}
onChangeText={setName}
/>
<Button title="Save Name" onPress={handleSave} />
</View>
);
};
export default App;
This example shows how to save a simple string (the user's name) in AsyncStorage
.
Here’s how to retrieve stored data from AsyncStorage
:
import { AsyncStorage } from 'react-native';
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [name, setName] = useState('');
useEffect(() => {
// Retrieve the name from AsyncStorage
AsyncStorage.getItem('userName').then((storedName) => {
if (storedName) {
setName(storedName);
}
});
}, []);
return (
<View>
<Text>Stored Name: {name}</Text>
</View>
);
};
export default App;
This code demonstrates how to retrieve stored data from AsyncStorage
and display it in the app.
In this example, we clear stored data using AsyncStorage
:
import { AsyncStorage } from 'react-native';
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [name, setName] = useState('');
const handleClear = () => {
// Clear the stored name from AsyncStorage
AsyncStorage.removeItem('userName');
setName(''); // Clear the state
};
return (
<View>
<Text>Stored Name: {name}</Text>
<Button title="Clear Stored Name" onPress={handleClear} />
</View>
);
};
export default App;
This example shows how to remove stored data from AsyncStorage
using the removeItem()
method.
In this example, we show how to save an object in AsyncStorage
:
import { AsyncStorage } from 'react-native';
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [user, setUser] = useState({ name: '', age: '' });
const handleSave = () => {
// Save the user object to AsyncStorage
AsyncStorage.setItem('userData', JSON.stringify(user));
};
return (
<View>
<Text>Enter your name:</Text>
<TextInput
placeholder="Name"
value={user.name}
onChangeText={(text) => setUser({ ...user, name: text })}
/>
<Text>Enter your age:</Text>
<TextInput
placeholder="Age"
value={user.age}
onChangeText={(text) => setUser({ ...user, age: text })}
/>
<Button title="Save User" onPress={handleSave} />
</View>
);
};
export default App;
This code demonstrates how to store an object (user data) in AsyncStorage
by stringifying the object before storing it.
Here’s how to use AsyncStorage
along with state management:
import { AsyncStorage } from 'react-native';
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [user, setUser] = useState({ name: '', age: '' });
useEffect(() => {
// Retrieve stored user data and update the state
AsyncStorage.getItem('userData').then((data) => {
if (data) {
setUser(JSON.parse(data));
}
});
}, []);
const handleSave = () => {
// Save the updated user object to AsyncStorage
AsyncStorage.setItem('userData', JSON.stringify(user));
};
return (
<View>
<Text>Name: {user.name}</Text>
<Text>Age: {user.age}</Text>
<Button title="Save User" onPress={handleSave} />
</View>
);
};
export default App;
This code shows how to combine state management with AsyncStorage
to save and retrieve an object, ensuring that the app state is synchronized with local storage.
Setting up Firebase in React Native: Firebase provides a backend-as-a-service (BaaS) platform that includes a real-time database, authentication services, storage, and more. To integrate Firebase into your React Native project, you need to configure Firebase SDK and initialize Firebase in your app. Firebase also provides various services like Cloud Firestore, Firebase Authentication, Cloud Messaging, etc. You'll need to configure Firebase and import necessary SDKs to start using these services.
Using Firestore for real-time database: Firestore is Firebase's NoSQL document-based database, offering flexibility and scalability. It allows you to store, sync, and query data in real-time across all clients. Firestore automatically handles real-time synchronization, making it suitable for applications like chats, live updates, and collaborative applications. Data in Firestore is stored as collections of documents, each containing fields and subcollections.
Authentication with Firebase: Firebase Authentication helps manage users with simple SDKs. It supports various authentication methods like email/password login, Google sign-in, Facebook login, and more. By using Firebase Authentication, you can easily manage user registration, login, and authentication without worrying about the backend. It provides seamless integration with Firestore for user-related data storage.
This example shows how to set up Firebase in your React Native project:
// First, install Firebase SDK in your project
// Run this command in your terminal:
// npm install --save @react-native-firebase/app
import { FirebaseApp } from '@react-native-firebase/app';
// Initialize Firebase with the configuration
const firebaseConfig = {
apiKey: 'YOUR_API_KEY',
authDomain: 'YOUR_AUTH_DOMAIN',
databaseURL: 'YOUR_DATABASE_URL',
projectId: 'YOUR_PROJECT_ID',
storageBucket: 'YOUR_STORAGE_BUCKET',
messagingSenderId: 'YOUR_MESSAGING_SENDER_ID',
appId: 'YOUR_APP_ID',
};
// Check if Firebase is already initialized
if (!FirebaseApp.apps.length) {
FirebaseApp.initializeApp(firebaseConfig); // Initialize Firebase with the config object
}
console.log("Firebase Initialized"); // Log the initialization status
This code initializes Firebase in your app by providing the necessary configuration from your Firebase project in the Firebase Console. Make sure to replace the placeholders with your actual Firebase configuration details.
This example demonstrates how to store data in Firestore:
import firestore from '@react-native-firebase/firestore';
import { View, Text, Button, TextInput } from 'react-native';
import React, { useState } from 'react';
const App = () => {
const [name, setName] = useState('');
const saveData = async () => {
// Reference to the 'users' collection in Firestore
const usersCollection = firestore().collection('users');
// Add a new document to the collection with the name
await usersCollection.add({
name: name,
timestamp: firestore.FieldValue.serverTimestamp(), // Add timestamp when the document is created
});
console.log('User added to Firestore');
};
return (
<View>
<TextInput
placeholder="Enter Name"
value={name}
onChangeText={setName}
/>
<Button title="Save User" onPress={saveData} />
</View>
);
};
export default App;
This example demonstrates how to add a new user to the Firestore 'users' collection. It saves the user's name and the timestamp when the document is created in Firestore.
This example shows how to fetch data from Firestore:
import firestore from '@react-native-firebase/firestore';
import { View, Text } from 'react-native';
import React, { useState, useEffect } from 'react';
const App = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
// Listen for real-time updates from the 'users' collection
const unsubscribe = firestore()
.collection('users')
.onSnapshot(querySnapshot => {
const usersList = [];
querySnapshot.forEach(documentSnapshot => {
usersList.push(documentSnapshot.data()); // Push the document data to the users list
});
setUsers(usersList); // Update the state with fetched data
});
return () => unsubscribe(); // Unsubscribe when the component unmounts
}, []);
return (
<View>
{users.map((user, index) => (
<Text key={index}>{user.name}</Text> // Display each user's name
))}
</View>
);
};
export default App;
This example listens for real-time changes in the Firestore 'users' collection and updates the UI with the user names whenever the data changes in Firestore.
This example demonstrates how to implement user login using Firebase Authentication:
import auth from '@react-native-firebase/auth';
import { View, Text, Button, TextInput } from 'react-native';
import React, { useState } from 'react';
const App = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async () => {
try {
// Sign in with email and password using Firebase Authentication
await auth().signInWithEmailAndPassword(email, password);
console.log('User logged in successfully');
} catch (error) {
console.error(error.message); // Log the error if authentication fails
}
};
return (
<View>
<TextInput
placeholder="Email"
value={email}
onChangeText={setEmail}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button title="Login" onPress={handleLogin} />
</View>
);
};
export default App;
This example shows how to handle user login with Firebase Authentication using email and password. If the login is successful, the user is authenticated.
This example demonstrates how to send push notifications using Firebase Cloud Messaging (FCM):
import messaging from '@react-native-firebase/messaging';
import { View, Text, Button } from 'react-native';
import React from 'react';
const App = () => {
const handleSendNotification = async () => {
// Request permission for push notifications
await messaging().requestPermission();
// Get the FCM token to send push notifications to this device
const token = await messaging().getToken();
console.log('FCM Token:', token); // Log the token (use this for sending push notifications)
// Example to send a push notification
messaging().sendMessage({
to: token,
notification: {
title: 'New Message',
body: 'You have a new notification',
},
});
console.log('Notification sent');
};
return (
<View>
<Button title="Send Notification" onPress={handleSendNotification} />
</View>
);
};
export default App;
This example demonstrates how to request push notification permissions, get the FCM token for the device, and send a push notification to the device using Firebase Cloud Messaging.
Performance optimization: In React Native, optimizing performance is crucial to ensure the app runs smoothly, especially on low-end devices. Performance bottlenecks can arise due to unnecessary renders, large image sizes, inefficient list rendering, or slow API calls. You can improve performance by using techniques such as memoization, lazy loading, and optimizing list rendering with FlatList or SectionList.
Using useEffect for side effects: The `useEffect` hook is a fundamental part of React and React Native that allows you to perform side effects in your functional components. Side effects include operations such as fetching data, subscriptions, timers, logging, and updating the DOM. `useEffect` runs after every render, but you can control its execution by passing dependencies to it.
Background tasks: Background tasks are operations that continue to run even when the app is not in the foreground, such as sending notifications, syncing data, or processing tasks in the background. React Native has libraries like `react-native-background-fetch` and `react-native-background-task` to help manage background tasks efficiently.
Deep linking: Deep linking enables an app to open a specific screen when a user clicks on a URL or receives a push notification. Deep linking is useful for handling links to content or actions within your app. React Native provides the `Linking` API to handle deep links and URL schemes to navigate to specific app screens.
This example demonstrates how to use the `useMemo` hook to memoize expensive calculations and avoid unnecessary re-renders:
import React, { useMemo, useState } from 'react';
import { View, Text, Button } from 'react-native';
const App = () => {
const [count, setCount] = useState(0);
// Expensive calculation (will be memoized)
const expensiveCalculation = useMemo(() => {
console.log('Calculating...');
return count * 2;
}, [count]); // Only re-compute when 'count' changes
return (
<View>
<Text>Count: {count}</Text>
<Text>Expensive Calculation: {expensiveCalculation}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
export default App;
The `useMemo` hook memoizes the expensive calculation, preventing it from being recalculated on every render, thus optimizing performance.
This example shows how to use the `useEffect` hook to make API calls when the component mounts:
import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
const App = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
// Fetch data on component mount using useEffect
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const jsonData = await response.json();
setData(jsonData);
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false);
}
};
fetchData();
}, []); // Empty dependency array means this effect runs once (on mount)
if (loading) {
return <ActivityIndicator size="large" />; // Show loading indicator
}
return (
<View>
<Text>Data: {JSON.stringify(data)}</Text>
</View>
);
};
export default App;
This example uses `useEffect` to fetch data from an API when the component mounts. The loading state is managed until the data is fetched.
This example shows how to set up background tasks using the `react-native-background-fetch` library:
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import BackgroundFetch from 'react-native-background-fetch';
const App = () => {
useEffect(() => {
// Configure background fetch
BackgroundFetch.configure(
{
minimumFetchInterval: 15, // Set the interval (in minutes) for background fetch
stopOnTerminate: false, // Keep running even after app is terminated
startOnBoot: true, // Start background fetch after device reboot
},
async () => {
console.log('Background task executed');
// Perform background tasks (e.g., syncing data, sending notifications)
},
error => {
console.log('Error in background fetch:', error);
}
);
return () => BackgroundFetch.stop(); // Stop background fetch when component unmounts
}, []);
return (
<View>
<Text>Background task is running...</Text>
</View>
);
};
export default App;
This example configures background tasks to run periodically using `react-native-background-fetch`. The background task will execute even if the app is not in the foreground.
This example demonstrates how to handle deep linking in React Native using the `Linking` API:
import React, { useEffect } from 'react';
import { View, Text, Linking } from 'react-native';
const App = () => {
useEffect(() => {
// Handle deep link when app is opened
const handleDeepLink = (event) => {
const { url } = event;
console.log('Deep link opened:', url);
// Navigate to the relevant screen based on the deep link
};
Linking.addEventListener('url', handleDeepLink); // Listen for deep links
// Check if app was opened from a deep link
Linking.getInitialURL().then((url) => {
if (url) {
console.log('App opened with URL:', url);
}
});
return () => Linking.removeEventListener('url', handleDeepLink); // Clean up listener
}, []);
return (
<View>
<Text>Listening for deep links...</Text>
</View>
);
};
export default App;
This example demonstrates how to use the `Linking` API to handle deep linking in React Native, allowing the app to open specific screens when a URL is clicked.
This example shows how to use React Native's debugging tools to debug an app:
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
const App = () => {
useEffect(() => {
// Example of a common bug (undefined variable)
const undefinedVar = undefined;
try {
console.log(undefinedVar.property); // This will throw an error
} catch (error) {
console.error('Error caught:', error);
// Use React Native Debugger or console logs to find issues
}
}, []);
return (
<View>
<Text>Debugging React Native App</Text>
</View>
);
};
export default App;
This example demonstrates how to use `console.log()` and `console.error()` to debug React Native apps and catch errors. You can also use tools like React Native Debugger for more advanced debugging features.
Native modules allow you to extend React Native by integrating platform-specific code written in Java or Swift/Objective-C. Bridging is the process of making this native code accessible from JavaScript, which is essential for accessing native features not exposed by React Native itself.
Topics covered:
This example demonstrates how to create a custom native module for iOS in Swift that exposes a camera functionality to React Native.
/* Swift Code: Create a custom module to access the device's camera. This is the iOS (Swift) implementation for React Native. */ import UIKit import AVFoundation import React @objc(CameraModule) class CameraModule: NSObject { @objc func captureImage(_ callback: @escaping RCTResponseSenderBlock) { // Accessing the camera (just a placeholder for camera logic) let camera = UIImage(named: "default.jpg") // Placeholder for actual camera capture logic callback([NSNull(), camera?.pngData()]) } } // Bridging to React Native @objc(CameraModule) extension CameraModule: RCTBridgeModule { static func moduleName() -> String { return "CameraModule" } }
Here's how you can call a function written in Swift/Objective-C from your JavaScript code using the NativeModules API.
// JavaScript code calling the native module function import { NativeModules } from 'react-native'; // Call the captureImage function from CameraModule NativeModules.CameraModule.captureImage((error, result) => { if (error) { console.error("Error capturing image: ", error); } else { console.log("Image captured successfully: ", result); } });
This example demonstrates how to handle errors in a native module, allowing React Native to gracefully handle any issues that occur during native operations.
/* Swift Code for error handling in native modules. This is part of the CameraModule implementation. */ import React import UIKit @objc(CameraModule) class CameraModule: NSObject { @objc func captureImage(_ callback: @escaping RCTResponseSenderBlock) { do { // Simulating camera access guard let camera = UIImage(named: "default.jpg") else { throw NSError(domain: "CameraError", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Unable to access the camera"]) } callback([NSNull(), camera.pngData()]) } catch let error { callback([error.localizedDescription, NSNull()]) } } }
In this example, we integrate the react-native-camera
library to access camera functionality on both iOS and Android.
// JavaScript code to use the React Native Camera library import React, { Component } from 'react'; import { View, Text } from 'react-native'; import { RNCamera } from 'react-native-camera'; export default class CameraScreen extends Component { render() { return (); } } Camera is ready
This example shows how to bridge communication between Java (Android) and Swift (iOS) native modules, allowing data sharing across platforms.
// Java Code (Android) package com.yourapp; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; public class SharedDataModule extends ReactContextBaseJavaModule { SharedDataModule(ReactApplicationContext reactContext) { super(reactContext); } @ReactMethod public void sendDataToSwift(String message) { // Send data to Swift (iOS) // This would involve using the bridge to send data // between Android and iOS (platform-specific implementation) } @Override public String getName() { return "SharedDataModule"; } }
// Swift Code (iOS) import React import Foundation @objc(SharedDataModule) class SharedDataModule: NSObject { @objc func receiveDataFromJava(_ message: String) { print("Data received from Android: \(message)") } @objc static func moduleName() -> String { return "SharedDataModule" } }
Testing is crucial to ensure the quality and reliability of mobile applications. React Native provides various tools and approaches for unit testing, end-to-end testing, and mocking components.
Topics covered:
This example demonstrates how to write a simple Jest test to check if a function or component behaves as expected.
// Jest unit test example import React from 'react'; import { render } from '@testing-library/react-native'; import MyComponent from './MyComponent'; // Importing the component to test // Jest test for rendering component test('it renders the component correctly', () => { const { getByText } = render(); const element = getByText('Hello, World!'); expect(element).toBeTruthy(); // Verifying that the text is rendered });
This example demonstrates setting up Detox to test the full flow of the app, simulating user interactions and verifying results.
// Detox end-to-end test example describe('Login Flow', () => { it('should show the login screen', async () => { await expect(element(by.id('login-screen'))).toBeVisible(); }); it('should log in successfully', async () => { await element(by.id('username-input')).typeText('user'); await element(by.id('password-input')).typeText('password'); await element(by.id('login-button')).tap(); await expect(element(by.id('home-screen'))).toBeVisible(); }); });
This example demonstrates how to use jest.mock() to mock an API call, ensuring that your tests don’t hit a real server.
// Jest mock API call example import { fetchData } from './api'; import { myFunction } from './myFunction'; // Mocking the fetchData API call jest.mock('./api', () => ({ fetchData: jest.fn(), })); test('it fetches data and updates the state', async () => { fetchData.mockResolvedValue({ data: 'mocked data' }); const result = await myFunction(); // Function that uses fetchData expect(result).toBe('mocked data'); // Verifying the result from mocked API });
This example demonstrates how to write a snapshot test to verify that the UI of a component remains consistent after changes.
// Jest snapshot test example import React from 'react'; import { render } from '@testing-library/react-native'; import MyComponent from './MyComponent'; test('it matches the snapshot', () => { const { toJSON } = render(); expect(toJSON()).toMatchSnapshot(); // Verifying that the rendered output matches the snapshot });
This example demonstrates how to test Redux actions and reducers to ensure state transitions happen correctly.
// Testing Redux actions and reducers import { addTodo } from './actions'; import todoReducer from './reducers'; // Jest test for action test('it creates an addTodo action', () => { const expectedAction = { type: 'ADD_TODO', payload: 'Learn React Native', }; expect(addTodo('Learn React Native')).toEqual(expectedAction); // Verifying the action is created correctly }); // Jest test for reducer test('it handles ADD_TODO action', () => { const initialState = []; const action = { type: 'ADD_TODO', payload: 'Learn React Native', }; const newState = todoReducer(initialState, action); expect(newState).toEqual(['Learn React Native']); // Verifying the state is updated correctly });
Deployment is the process of making the app available for users on app stores (iOS and Android). React Native supports deploying apps with various configurations, including over-the-air updates.
Topics covered:
This example demonstrates how to create a production build of your app for iOS using Xcode.
// Steps to create a release build for iOS using Xcode: // 1. Open your React Native project in Xcode. // 2. Go to the 'Product' menu and select 'Archive' to create a production build. // 3. After archiving, select 'Distribute App' to upload to the App Store or to a local device.
This example demonstrates how to prepare your app for submission to the Google Play Store, including setting up a key store and uploading the APK.
// Steps to prepare an Android app for Google Play distribution: // 1. Generate a signed APK using the key store: // - Create or use an existing keystore file. // - Configure your React Native app's build.gradle to use the keystore. // 2. Build the APK for release using the following command: // react-native run-android --variant=release // 3. Upload the APK to the Google Play Console for submission.
This example demonstrates how to configure CodePush in your app to deliver over-the-air updates for bug fixes or small improvements.
// Steps to configure CodePush for OTA updates: // 1. Install the CodePush package: // npm install --save react-native-code-push // 2. Link the CodePush module to your app: // react-native link react-native-code-push // 3. In your app, use CodePush to synchronize updates: // import CodePush from 'react-native-code-push'; // let codePushOptions = { checkFrequency: CodePush.CheckFrequency.ON_APP_START }; // export default CodePush(codePushOptions)(YourApp);
This example demonstrates how to set up Firebase to send push notifications to your React Native app.
// Steps to integrate Firebase Cloud Messaging (FCM) for push notifications: // 1. Install Firebase dependencies: // npm install --save @react-native-firebase/app @react-native-firebase/messaging // 2. Link Firebase with your app using the Firebase Console. // 3. Add the Firebase configuration files to your app (google-services.json for Android, GoogleService-Info.plist for iOS). // 4. Request permission for push notifications on both iOS and Android: // import messaging from '@react-native-firebase/messaging'; // await messaging().requestPermission(); // 5. Listen for incoming messages: // messaging().onMessage(async remoteMessage => { // console.log('FCM message received', remoteMessage); // });
This example demonstrates how to implement a continuous integration and deployment pipeline to automatically test and deploy your React Native app.
// Steps to set up CI/CD for React Native: // 1. Choose a CI/CD tool like CircleCI, GitHub Actions, or Bitrise. // 2. Set up a basic configuration file (e.g., circleci.yml for CircleCI) to automate the build and test process. // Example CircleCI configuration: // jobs: // build: // docker: // - image: circleci/python:3.7 // steps: // - checkout // - run: // name: Install Dependencies // command: npm install // - run: // name: Run Tests // command: npm test // 3. Once tests are passed, set up deployment to the app stores or to a staging environment.
TypeScript adds static typing to JavaScript, which helps prevent bugs and improves development speed by providing early feedback.
Topics covered:
This example demonstrates how to add TypeScript support to a React Native project and configure `tsconfig`.
// Steps to set up TypeScript in a React Native project: // 1. Install TypeScript and necessary types: // npm install --save-dev typescript @types/react @types/react-native // 2. Add a `tsconfig.json` file to your project with the following configuration: { "compilerOptions": { "allowJs": true, "noEmit": true, "isolatedModules": true, "strict": true, "jsx": "react-native" }, "include": [ "src/**/*" ] } // 3. Rename `.js` files to `.tsx` for React components or `.ts` for non-React files.
This example demonstrates how to create a functional component that uses TypeScript for typing props and state.
// Defining the type for props: interface MyComponentProps { name: string; age: number; } // Defining a functional component with typed props: const MyComponent: React.FC= ({ name, age }) => { return ( ); } export default MyComponent;{name}
Age: {age}
This example demonstrates how to define explicit types for component state and props to avoid runtime errors.
// Defining types for component state and props: interface CounterState { count: number; } interface CounterProps { initialCount: number; } class Counter extends React.Component{ constructor(props: CounterProps) { super(props); this.state = { count: props.initialCount }; } increment = () => { this.setState({ count: this.state.count + 1 }); }; render() { return ( ); } } export default Counter;{this.state.count}
This example demonstrates how to set up Redux in a React Native project using TypeScript for actions, reducers, and store.
// Defining types for Redux actions: interface IncrementAction { type: 'INCREMENT'; } interface DecrementAction { type: 'DECREMENT'; } type CounterAction = IncrementAction | DecrementAction; // Defining the state type: interface CounterState { count: number; } // Reducer function with TypeScript: const counterReducer = (state: CounterState = { count: 0 }, action: CounterAction): CounterState => { switch (action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }; // Setting up the store with TypeScript: import { createStore } from 'redux'; const store = createStore(counterReducer);
This example demonstrates how to define types for API responses and use them in network requests to ensure type safety.
// Defining the type for API response: interface User { id: number; name: string; email: string; } const fetchUser = async (userId: number): Promise=> { const response = await fetch(`https://api.example.com/users/${userId}`); const data: User = await response.json(); return data; }; // Calling the API function: fetchUser(1).then(user => { console.log(user.name); // Accessing type-safe properties });
Performance optimization in React Native involves improving the speed, memory usage, and responsiveness of the app.
Topics covered:
This example demonstrates how to use `React.memo` to prevent unnecessary re-renders of components and improve performance.
// Wrapping a component with React.memo to avoid re-renders unless props change: const MyComponent = React.memo(({ name }) => { console.log('Rendering MyComponent'); return{name}
; }); // The component will only re-render if the 'name' prop changes.
This example shows how to implement lazy loading using React’s `Suspense` and `lazy` to load components only when they are needed.
// Using React's lazy and Suspense for lazy loading components: import React, { Suspense, lazy } from 'react'; const MyLazyComponent = lazy(() => import('./MyLazyComponent')); const App = () => { return (Loading...
This example demonstrates how to use Flipper, a debugging tool, to inspect your app’s performance and diagnose issues.
// Step 1: Install Flipper and connect it to your React Native app. // Step 2: Enable performance profiling in Flipper by selecting the Performance tab. // Step 3: Analyze the timeline, CPU usage, and memory usage to identify performance bottlenecks. // Example: Check for unnecessary re-renders or slow functions causing performance issues.
This example shows how to enable Hermes, a JavaScript engine, to reduce the app's bundle size and improve performance.
// To enable Hermes, modify the `android/app/build.gradle` file as follows: // 1. In `project.ext.react`, set `enableHermes: true`. // 2. Rebuild the app to generate a smaller bundle size. project.ext.react = [ enableHermes: true, // Enable Hermes // other settings ]; // Rebuild the app for the changes to take effect.
This example demonstrates how to implement `shouldComponentUpdate` lifecycle method in class components to prevent re-renders when unnecessary.
// Implementing shouldComponentUpdate to prevent re-renders: class MyComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { // Only re-render if the 'name' prop changes return nextProps.name !== this.props.name; } render() { console.log('Rendering MyComponent'); return{this.props.name}
; } }
Custom components and libraries allow you to create reusable UI elements and share them across projects.
Topics covered:
This example demonstrates how to create a custom button component that can be reused throughout your app.
// Reusable Button Component import React from 'react'; import { TouchableOpacity, Text, StyleSheet } from 'react-native'; const MyButton = ({ title, onPress }) => { return (); }; const styles = StyleSheet.create({ button: { backgroundColor: '#4CAF50', padding: 10, borderRadius: 5, alignItems: 'center', }, text: { color: 'white', fontSize: 16, }, }); export default MyButton; {title}
This example shows how to build a custom slider component with customizable properties like min, max, and step values.
// Custom Slider Component import React from 'react'; import { Slider, View, Text } from 'react-native'; const MySlider = ({ min, max, step, value, onValueChange }) => { return (); }; export default MySlider; Slider Value: {value}
This example demonstrates how to package your custom components into a library and publish it to npm for sharing.
// Step 1: Initialize a new npm package // Run `npm init` to create a package.json file // Step 2: Add your custom components to the library // Example: Save your custom components in a 'src' folder // Step 3: Publish to npm // Run `npm publish` to publish the package to npm // Example of package.json { "name": "my-react-native-library", "version": "1.0.0", "main": "index.js", "scripts": { "test": "jest" }, "dependencies": { "react-native": "^0.64.0" } }
This example shows how to style your components using `styled-components` to keep the styles modular and reusable.
// Using styled-components for styling a button import React from 'react'; import styled from 'styled-components/native'; const Button = styled.TouchableOpacity` background-color: #4CAF50; padding: 10px; border-radius: 5px; align-items: center; `; const ButtonText = styled.Text` color: white; font-size: 16px; `; const MyStyledButton = ({ title, onPress }) => { return ( ); }; export default MyStyledButton;
This example demonstrates how to add accessibility properties to custom components to make them usable by people with disabilities.
// Adding accessibility props to a button component import React from 'react'; import { TouchableOpacity, Text } from 'react-native'; const AccessibleButton = ({ title, onPress }) => { return (); }; export default AccessibleButton; {title}