✅ Chapter 1: Core React Native
🔷 JSX & Components
👉 JSX (JavaScript XML)
JSX lets you write HTML-like syntax in JavaScript. It’s how you describe the UI.
import React from 'react';
import { Text, View } from 'react-native';
const MyComponent = () => {
return (
<View>
<Text>Hello React Native!</Text>
</View>
);
};
● View is like a <div>, used for layout.
● Text is for displaying text (no <p> or <h1> in RN).
👉 Components
Two types:
1. Functional Component – most commonly used now
2. Class Component – older, less used now
// Functional
const Welcome = () => <Text>Welcome!</Text>;
✅ Best Practice: Break your UI into small reusable components.
🔷 State & Props
✅ State (local, dynamic data)
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>Count: {count}</Text>
<Button title="Increase" onPress={() => setCount(count + 1)} />
</View>
);
};
✅ Props (data from parent to child)
const Greeting = ({ name }) => <Text>Hello, {name}</Text>;
<Greeting name="Preeti" />
🔷 Flexbox Layout
React Native uses Flexbox for layout (default is flexDirection: 'column').
Example:
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text>Left</Text>
<Text>Right</Text>
</View>
Common Flexbox Props:
● flexDirection: row / column
● justifyContent: center / space-between / space-around
● alignItems: center / flex-start / flex-end
🔷 Stylesheets
Use StyleSheet.create() or inline styles.
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
padding: 10,
},
title: {
fontSize: 24,
fontWeight: 'bold',
},
});
Apply like:
<View style={styles.container}>
<Text style={styles.title}>Styled Text</Text>
</View>
🔷 ScrollView, FlatList, SectionList
✅ ScrollView – scrollable content
<ScrollView>
<Text>Item 1</Text>
<Text>Item 2</Text>
...
</ScrollView>
⚠️ Not optimized for large data.
✅ FlatList – performant list (recommended)
<FlatList
data={[{ id: '1', title: 'Item 1' }, { id: '2', title: 'Item 2' }]}
renderItem={({ item }) => <Text>{item.title}</Text>}
keyExtractor={item => item.id}
/>
✅ SectionList – grouped lists
<SectionList
sections={[
{ title: 'Fruits', data: ['Apple', 'Banana'] },
{ title: 'Vegetables', data: ['Carrot', 'Peas'] },
]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => <Text style={{ fontWeight: 'bold' }}>{section.title}</Text>}
/>
🔷 Touchable & Pressable Components
Used to detect taps (like buttons):
✅ TouchableOpacity (most used)
<TouchableOpacity onPress={() => alert('Clicked!')}>
<Text>Press Me</Text>
</TouchableOpacity>
✅ Pressable (newer, supports more styles)
<Pressable onPress={() => console.log('Pressed')}>
<Text>Pressable</Text>
</Pressable>
🧠 Summary of Chapter 1:
Topic Purpose
JSX Write UI with HTML-like syntax in JavaScript
Components Divide UI into reusable pieces
State & Props Manage dynamic data and pass info between
components
Flexbox Layout Control layout using flex properties
Stylesheets Apply styling to components
ScrollView / FlatList Show scrollable or dynamic list of items
Touchable / Handle user interaction (click/tap)
Pressable
✅ Chapter 2: React Basics (Must Know)
🔷 1. Functional Components
Functional components are plain JavaScript functions that return JSX.
✅ Syntax:
import React from 'react';
const Greeting = ({ name }) => {
return <h1>Hello, {name}</h1>;
};
export default Greeting;
● Simple and reusable
● Recommended over class components
● Can use Hooks like useState, useEffect for logic
🔷 2. Hooks
Hooks allow you to use state and lifecycle methods inside functional components.
✅ useState – Add state to a function
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0); // initial value is 0
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</>
);
};
✅ useEffect – Handle side effects (API calls, timers)
import React, { useEffect } from 'react';
useEffect(() => {
console.log('Component mounted');
return () => {
console.log('Component will unmount');
};
}, []);
💡 useEffect(() => {}, []) acts like componentDidMount.
✅ useRef – Keep a mutable reference without re-render
import React, { useRef } from 'react';
const InputFocus = () => {
const inputRef = useRef();
const handleFocus = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={handleFocus}>Focus Input</button>
</>
);
};
🔧 Can also be used for timers, scroll positions, and persisting values across
renders.
🔷 3. Component Lifecycle
In functional components, lifecycle methods are simulated with useEffect:
Class Component Functional Equivalent
componentDidMount useEffect(() => {}, [])
componentDidUpdate useEffect(() => {}, [state])
componentWillUnmou useEffect(() => return () => {}, [])
nt
useEffect(() => {
console.log("mounted");
return () => {
console.log("cleanup on unmount");
};
}, []);
🔷 4. Conditional Rendering
Change the UI based on conditions.
✅ Ternary Operator
{isLoggedIn ? <Dashboard /> : <Login />}
✅ Logical AND
{user && <p>Welcome, {user.name}</p>}
✅ Using a function
const renderContent = () => {
if (loading) return <p>Loading...</p>;
return <p>Data Loaded</p>;
};
🔷 5. Context API
Used for sharing global state (theme, user info) between components without passing props
manually.
✅ Step 1: Create Context
import React from 'react';
const ThemeContext = React.createContext();
✅ Step 2: Provide Context
<ThemeContext.Provider value="dark">
<MyComponent />
</ThemeContext.Provider>
✅ Step 3: Consume Context (useContext)
import React, { useContext } from 'react';
const MyComponent = () => {
const theme = useContext(ThemeContext);
return <p>Current theme is {theme}</p>;
};
💡 You can store user details, themes, language settings, etc.
🧠 Summary Table
Concept Use Case
Functional Component Building UI using functions
useState Handle local component state
useEffect Handle side effects (API, timers, cleanup)
useRef Access DOM nodes or persist values without
re-render
Lifecycle Control behavior during mount, update, unmount
Conditional Render Dynamically show/hide UI based on conditions
Context API Share data across components without prop drilling
🛠 Practice Suggestion
Build a To-Do App using:
● useState for storing tasks
● useEffect for logging or syncing to storage
● useRef for input focus
● Conditional Rendering for empty vs. task list
● Context for global theme or user
✅ Chapter 3: Navigation in React Native
React Native doesn’t come with built-in navigation. So we use a popular library:
📦 React Navigation
Install it using:
npm install @react-navigation/native
Then install the dependencies:
npx expo install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack @react-navigation/bottom-tabs
@react-navigation/drawer
Wrap your app with the NavigationContainer:
import { NavigationContainer } from '@react-navigation/native';
export default function App() {
return (
<NavigationContainer>
{/* Your Navigator goes here */}
</NavigationContainer>
);
}
🔷 1. Types of Navigation
🧭 Stack Navigation
Used for "push and go back" style, like moving between pages.
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
You can navigate like:
navigation.navigate('Profile');
📑 Tab Navigation
Used when you want bottom navigation (like Instagram, Facebook).
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
📂 Drawer Navigation
Used for a side menu (like Gmail app).
import { createDrawerNavigator } from '@react-navigation/drawer';
const Drawer = createDrawerNavigator();
<Drawer.Navigator>
<Drawer.Screen name="Dashboard" component={DashboardScreen} />
<Drawer.Screen name="Notifications" component={NotificationScreen} />
</Drawer.Navigator>
🔷 2. Passing Params Between Screens
👉 Send Params:
navigation.navigate('Profile', { userId: 123 });
👉 Receive Params:
const route = useRoute();
console.log(route.params.userId);
OR directly in component:
function ProfileScreen({ route }) {
const { userId } = route.params;
return <Text>User ID: {userId}</Text>;
}
🔷 3. Navigation Reset, GoBack, Replace
🔄 Reset Navigation Stack
navigation.reset({
index: 0,
routes: [{ name: 'Login' }],
});
⬅️ Go Back
navigation.goBack();
🔁 Replace current screen
navigation.replace('Dashboard');
🔐 Common Use Case:
● After login, replace login screen with home screen so user can’t go back.
● Pass params to show data on next screen.
● Use drawer or tabs to organize app sections.
🧠 Summary Table
Feature Usage
Stack Navigator Navigate forward/back between
screens
Tab Navigator Bottom navigation bar
Drawer Navigator Slide-out side menu
navigate() Move to another screen
goBack() Go to previous screen
replace() Replace current screen
reset() Clear navigation history
Pass Params Share data between screens
🛠 Practice Task:
Build a 3-screen app:
1. HomeScreen: with a button → navigate to DetailsScreen
2. DetailsScreen: display passed data
3. SettingsScreen: accessible via drawer or tab
✅ Chapter 4: UI/UX Components in React
Native
These components are used to improve usability, handle interactions, and enhance the
user experience.
🔷 1. Custom Header, Button, and Input
🧭 Custom Header
React Navigation offers a default header, but you can customize or create your own.
import { View, Text, StyleSheet } from 'react-native';
const CustomHeader = () => (
<View style={styles.header}>
<Text style={styles.title}>My App</Text>
</View>
);
const styles = StyleSheet.create({
header: {
backgroundColor: '#2196F3',
padding: 15,
},
title: {
color: 'white',
fontSize: 20,
fontWeight: 'bold',
},
});
📌 You can replace screen headers using options in React Navigation:
<Stack.Screen name="Home" component={HomeScreen} options={{ header: () =>
<CustomHeader /> }} />
🔘 Custom Button
Use Touchable components to build your own buttons.
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
const CustomButton = ({ label, onPress }) => (
<TouchableOpacity style={styles.btn} onPress={onPress}>
<Text style={styles.text}>{label}</Text>
</TouchableOpacity>
);
const styles = StyleSheet.create({
btn: {
backgroundColor: '#673ab7',
padding: 10,
borderRadius: 8,
margin: 10,
},
text: {
color: 'white',
textAlign: 'center',
},
});
📝 Custom Input
React Native provides TextInput for capturing user input.
import { TextInput } from 'react-native';
<TextInput
placeholder="Enter your name"
value={name}
onChangeText={setName}
style={{
borderWidth: 1,
padding: 10,
margin: 10,
borderRadius: 5,
}}
/>
🔷 2. Modal & Bottom Sheet
🪟 Modal
Used to show dialogs or pop-ups over the screen.
import { Modal, View, Text, Button } from 'react-native';
<Modal visible={showModal} transparent animationType="slide">
<View style={{ backgroundColor: '#000000aa', flex: 1, justifyContent: 'center' }}>
<View style={{ backgroundColor: '#fff', margin: 20, padding: 20, borderRadius: 10 }}>
<Text>This is a modal!</Text>
<Button title="Close" onPress={() => setShowModal(false)} />
</View>
</View>
</Modal>
⬆️ Bottom Sheet
For that sliding-up drawer (like WhatsApp media sharing):
Use a library like:
npm install @gorhom/bottom-sheet
Usage (simplified):
import BottomSheet from '@gorhom/bottom-sheet';
<BottomSheet
snapPoints={['25%', '50%']}
index={1}
>
<View><Text>Hello Bottom Sheet</Text></View>
</BottomSheet>
🔷 3. Toast / Snackbar
These are temporary messages (like "Form submitted!", "Error occurred").
✅ Toast (for Android only by default):
import { ToastAndroid } from 'react-native';
ToastAndroid.show("Hello Toast!", ToastAndroid.SHORT);
✅ Cross-platform Snackbar (better UX)
Use a library like:
npm install react-native-paper
import { Snackbar } from 'react-native-paper';
<Snackbar
visible={visible}
onDismiss={() => setVisible(false)}
duration={3000}
>
Action completed!
</Snackbar>
🔷 4. Keyboard Handling
When input fields are focused, the keyboard may overlap UI. To prevent this:
✅ Use KeyboardAvoidingView
import { KeyboardAvoidingView, Platform } from 'react-native';
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{ flex: 1 }}
>
{/* Your Form/Input Components */}
</KeyboardAvoidingView>
✅ Also wrap in ScrollView if needed:
<ScrollView keyboardShouldPersistTaps="handled">
{/* Input fields */}
</ScrollView>
🧠 Summary Table
Component Purpose
Custom Header Personalized screen titles/navigation
Custom Button Stylized action triggers
TextInput Get input from the user
Modal Pop-up overlay for alerts/forms
Bottom Sheet Slide-up UI for actions/info
Toast / Snackbar Show quick feedback
Keyboard Handling Prevent keyboard from overlapping UI
🛠 Mini Project Idea:
Make a Login Screen with:
● 2 TextInputs (email + password)
● A CustomButton to submit
● Show a Snackbar on successful login
● Use KeyboardAvoidingView to handle keyboard
✅ Chapter 5: API & Networking in React
Native
🔷 1. Making API Calls (Axios / Fetch)
✅ Using fetch() (built-in in React Native)
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
}, []);
✅ Using axios (more powerful)
Install:
npm install axios
Usage:
import axios from 'axios';
useEffect(() => {
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => console.log(response.data))
.catch(error => console.log(error));
}, []);
🔷 2. HTTP Methods: GET / POST / PUT / DELETE
✅ GET (Read data)
axios.get('https://api.example.com/users')
✅ POST (Send data)
axios.post('https://api.example.com/users', {
name: 'Preeti',
email: '[email protected]',
});
✅ PUT (Update data)
axios.put('https://api.example.com/users/1', {
name: 'Updated Name',
});
✅ DELETE (Remove data)
axios.delete('https://api.example.com/users/1');
🔷 3. Error Handling
Always handle errors to improve UX and avoid crashes.
axios.get(url)
.then(res => setData(res.data))
.catch(err => {
console.error(err);
Alert.alert("Error", "Something went wrong!");
});
🔷 4. Async/Await & Promises
✅ Promise Style:
axios.get(url)
.then(res => console.log(res.data))
.catch(err => console.log(err));
✅ Async/Await Style (cleaner):
const fetchData = async () => {
try {
const response = await axios.get(url);
setData(response.data);
} catch (error) {
console.error(error);
};
useEffect(() => {
fetchData();
}, []);
🔁 Good for readability and better error control
🔷 5. Token-Based Authentication
Apps often need to log in and store a token to make secure requests.
✅ Step-by-step:
1. User logs in → receive token from server
2. Save token in AsyncStorage
3. Send token with headers in API calls
💾 Save token:
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('token', response.data.token);
📤 Use token in request:
const token = await AsyncStorage.getItem('token');
axios.get('https://api.example.com/profile', {
headers: {
Authorization: `Bearer ${token}`,
},
});
🧠 Summary Table
Concept Purpose
fetch() / axios To make HTTP requests
GET Read data from server
POST Send new data to server
PUT Update existing data
DELETE Remove data
Error Handling Catch and show errors
Async/Await Cleaner syntax for promises
Token Auth Secure API calls with authentication
tokens
🛠 Mini Project Idea
Build a User List App:
● Use axios to fetch users from https://jsonplaceholder.typicode.com/users
● Display in a FlatList
● Add a button to POST a new user (simulate form)
Show error toast if request fails
⚙️ Chapter 6: State Management
🔑 Why State Management?
In small apps, you use useState.
But in medium/large apps, where data is shared across multiple components (e.g., user info,
cart, theme), managing state becomes complex.
So, we use tools like:
● React Context – for light global state
● Redux – for structured state management
● Redux Toolkit – modern & easier way to use Redux
✅ 1. React Context API (for light global state)
📌 Used for:
● Theme (dark/light)
● Auth info (logged in user)
● Language settings
✅ Create a Context
import React, { createContext } from 'react';
export const ThemeContext = createContext();
✅ Provide Context in root
const App = () => {
return (
<ThemeContext.Provider value="dark">
<YourApp />
</ThemeContext.Provider>
);
};
✅ Consume Context in child
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
const MyComponent = () => {
const theme = useContext(ThemeContext);
return <Text>Theme is {theme}</Text>;
};
🧠 Use when:
● App is small or medium
● You only need to share a few variables (theme, language, user)
✅ 2. Redux (standard library for large-scale state)
📌 Used for:
● Centralized data (products, cart, user, settings)
● Predictable structure
● Debugging & Time travel (with Redux DevTools)
🔧 Install Redux
npm install redux react-redux
✅ Create Store
import { createStore } from 'redux';
const initialState = {
count: 0,
};
const reducer = (state = initialState, action) => {
switch(action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
default:
return state;
};
export const store = createStore(reducer);
✅ Provide Store in root
import { Provider } from 'react-redux';
import { store } from './store';
const App = () => (
<Provider store={store}>
<YourApp />
</Provider>
);
✅ Use Redux in components
import { useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<>
<Text>{count}</Text>
<Button title="+" onPress={() => dispatch({ type: 'INCREMENT' })} />
</>
);
};
✅ 3. Redux Toolkit (recommended)
Redux Toolkit simplifies Redux setup with less boilerplate.
🔧 Install
npm install @reduxjs/toolkit react-redux
✅ Setup Slice
// counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: state => { state.count += 1; },
decrement: state => { state.count -= 1; },
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
✅ Setup Store
// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
✅ Use in App
import { Provider } from 'react-redux';
import { store } from './store';
<Provider store={store}>
<App />
</Provider>
✅ Use in Component
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';
const Counter = () => {
const count = useSelector(state => state.counter.count);
const dispatch = useDispatch();
return (
<>
<Text>{count}</Text>
<Button title="+" onPress={() => dispatch(increment())} />
</>
);
🧠 Summary Table
};
Tool Use Case Pros Cons
useState Local, simple state Fast, native Not shareable globally
Context API Small apps, global Easy, no dependency Re-renders on every
config change
Redux Large apps, structured Debuggable, scalable Boilerplate-heavy
state
Redux Modern Redux Less code, better Still a bit setup-heavy
Toolkit defaults
🛠 Practice Task
Create a simple counter app with:
● Redux Toolkit
● Buttons to increment and decrement count
● Global state visible across two screens
✅ Chapter 7: Utilities & Helpers in React
Native
Utilities are custom functions or libraries that you write or reuse to avoid repeating code.
They make your app:
● Easier to maintain
● More modular
● More readable
🔷 1. Date/Time Formatting
Date/time comes in raw formats (like 2025-07-14T12:00:00Z).
We use date formatting helpers to convert them into readable formats.
✅ Using Date manually
const raw = "2025-07-14T12:00:00Z";
const date = new Date(raw);
const formatted = `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`;
// Output: 14-7-2025
✅ Using dayjs or date-fns (Recommended)
Install:
npm install dayjs
Example:
import dayjs from 'dayjs';
const raw = "2025-07-14T12:00:00Z";
const formatted = dayjs(raw).format('DD MMM YYYY, hh:mm A');
// Output: "14 Jul 2025, 05:30 PM"
💡 You can also calculate time differences:
dayjs().to(dayjs('2025-07-14T10:00:00')); // "in 2 hours"
🔷 2. Reusable Utility Functions
These are your custom helper files (like utils.js) where you store logic that's used in multiple
places.
✅ Example: Capitalize string
export const capitalize = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
✅ Example: Validate email
export const isValidEmail = (email) => {
const re = /\S+@\S+\.\S+/;
return re.test(email);
};
Use in components:
import { isValidEmail } from './utils';
if (!isValidEmail(email)) {
alert('Enter a valid email');
🔷 3. Constants File
Instead of hardcoding strings or colors everywhere, store them in a separate file:
// constants.js
export const COLORS = {
primary: '#4CAF50',
secondary: '#FFC107',
};
export const MESSAGES = {
WELCOME: 'Welcome to the app!',
ERROR: 'Something went wrong!',
};
Use like:
<Text style={{ color: COLORS.primary }}>{MESSAGES.WELCOME}</Text>
🔷 4. Common Format Helpers
● Currency Formatter
export const formatCurrency = (amount) => {
return `₹${Number(amount).toFixed(2)}`;
};
● Phone Formatter
export const formatPhone = (num) => {
return num.replace(/(\d{5})(\d{5})/, '$1 $2');
};
🔷 5. Platform/Device Helpers
React Native provides a Platform module:
import { Platform } from 'react-native';
if (Platform.OS === 'android') {
// Do something specific for Android
You can even write conditional styles:
const styles = StyleSheet.create({
text: {
fontSize: Platform.OS === 'ios' ? 20 : 18,
},
});
🧠 Summary Table
Utility Type Purpose
Date Formatter Display dates in human-friendly formats
Validation Helpers Check email, phone, password, etc.
Constants File Centralized app text, colors, messages
Currency Helpers Format money consistently (e.g., ₹120.00)
Platform Helpers Detect platform (iOS/Android) for UI tweaks
🛠 Practice Task
Create a utils.js file with:
● formatDate() using dayjs
● capitalize() for strings
● isValidEmail()
● COLORS and MESSAGES constants
Use them in a simple profile screen with:
● Formatted date of birth
● Capitalized name
● Email validation on form submit
✅ Chapter 8: Forms & Validation in React
Native
🔷 1. TextInput Handling
React Native provides TextInput to collect user input.
✅ Basic Example:
import React, { useState } from 'react';
import { TextInput, Text, View } from 'react-native';
const MyForm = () => {
const [name, setName] = useState('');
return (
<View>
<TextInput
placeholder="Enter your name"
value={name}
onChangeText={text => setName(text)}
style={{
borderWidth: 1,
padding: 10,
margin: 10,
borderRadius: 6,
}}
/>
<Text>Hello, {name}</Text>
</View>
);
};
🔑 onChangeText updates state, and value binds it.
🔷 2. Handling Multiple Inputs
const [form, setForm] = useState({ email: '', password: '' });
<TextInput
placeholder="Email"
value={form.email}
onChangeText={(text) => setForm({ ...form, email: text })}
/>
<TextInput
placeholder="Password"
secureTextEntry
value={form.password}
onChangeText={(text) => setForm({ ...form, password: text })}
/>
🔷 3. Manual Validation
You can validate input with basic logic before form submission.
✅ Example: Simple email/password check
const handleSubmit = () => {
if (!form.email.includes('@')) {
alert('Invalid email');
} else if (form.password.length < 6) {
alert('Password too short');
} else {
alert('Form submitted!');
};
🔷 4. Using Libraries for Form & Validation
Manually validating can be error-prone. Use libraries like:
✅ 🧰 react-hook-form (lightweight & powerful)
Install:
npm install react-hook-form
Basic usage:
import { useForm, Controller } from 'react-hook-form';
import { TextInput, Button, Text, View } from 'react-native';
const MyForm = () => {
const { control, handleSubmit } = useForm();
const onSubmit = data => console.log(data);
return (
<View>
<Controller
control={control}
name="email"
rules={{ required: true }}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Email"
value={value}
onChangeText={onChange}
style={{ borderWidth: 1, padding: 8, margin: 8 }}
/>
)}
/>
<Button title="Submit" onPress={handleSubmit(onSubmit)} />
</View>
);
};
✅ ✅ With Validation: yup + react-hook-form
Install:
npm install yup @hookform/resolvers
Define a validation schema:
import * as yup from 'yup';
const schema = yup.object({
email: yup.string().email().required(),
password: yup.string().min(6).required(),
});
Use it:
const { control, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(schema),
});
Show error messages:
{errors.email && <Text style={{ color: 'red' }}>Invalid Email</Text>}
🔷 5. Secure Inputs
For passwords and sensitive data:
<TextInput secureTextEntry={true} placeholder="Password" />
🔷 6. Submit Button with Validation
<Button title="Submit" onPress={handleSubmit(onSubmit)} />
Disable the button when required fields are empty, or show loader:
<Button title="Submit" disabled={!form.email || !form.password} />
🧠 Summary Table
Feature Purpose
TextInput Capture user input
useState Track and update input values
Manual Validation Validate email, password, etc.
react-hook-form Handle form data efficiently
yup Create validation rules
secureTextEntry Hide password field text
Error Handling Show user-friendly validation info
🛠 Practice Task
Create a Login Form with:
● TextInput for email & password
● react-hook-form + yup validation
● Error messages below each field
● Submit button that shows alert on valid input
✅ Chapter 9: Storage in React Native
We’ll cover:
● AsyncStorage (basic key-value storage)
● Secure Storage (for sensitive data like tokens/passwords)
🔷 1. AsyncStorage (Simple Local Storage)
📦 Install AsyncStorage
npm install @react-native-async-storage/async-storage
✅ Store Data
import AsyncStorage from '@react-native-async-storage/async-storage';
const storeData = async () => {
try {
await AsyncStorage.setItem('username', 'Preeti');
} catch (error) {
console.error('Error saving data', error);
};
✅ Retrieve Data
const getData = async () => {
try {
const value = await AsyncStorage.getItem('username');
if (value !== null) {
console.log('Username:', value);
} catch (error) {
console.error('Error reading value', error);
};
✅ Remove Data
await AsyncStorage.removeItem('username');
✅ Clear All Storage
await AsyncStorage.clear();
🧠 Use Cases for AsyncStorage:
Use Case Key
Save login token "authToken"
Remember user "darkMode",
preferences "language"
Store last-visited screen "lastScreen"
Local user profile "userProfile" (JSON)
🔐 For complex objects, always store using JSON.stringify() and read with
JSON.parse()
const user = { name: 'Preeti', email: '[email protected]' };
await AsyncStorage.setItem('user', JSON.stringify(user));
const savedUser = JSON.parse(await AsyncStorage.getItem('user'));
🔒 2. Secure Storage (for Sensitive Data)
For login tokens or passwords, use libraries like:
✅ react-native-encrypted-storage
npm install react-native-encrypted-storage
📦 Store Securely:
import EncryptedStorage from 'react-native-encrypted-storage';
await EncryptedStorage.setItem(
'auth_token',
JSON.stringify({ token: 'abc123' })
);
🔐 Retrieve Securely:
const session = await EncryptedStorage.getItem('auth_token');
if (session !== null) {
const { token } = JSON.parse(session);
🔁 Best Practice Flow (Login Example)
1. User logs in → Receive token
2. Save token in AsyncStorage or EncryptedStorage
3. On app launch → Check for token
4. If token exists → Navigate to Home
✅ Summary Table
Storage Type Use Case Secure Supports
? JSON?
AsyncStorage Basic preferences, ❌ ✅
non-sensitive
EncryptedStorage Tokens, passwords ✅ ✅
SecureStore Alternative for Expo apps ✅ ✅
(Expo)
🛠 Mini Project Suggestion
Build a Login + Logout flow using:
● Login screen with form
● On submit, store "token" in AsyncStorage
● Navigate to Home
● Add "Logout" button → clears AsyncStorage
✅ Chapter 10: Native Modules in React
Native
🔍 What are Native Modules?
Native Modules are platform-specific functionalities (Android/iOS) written in Java/Kotlin or
Swift/Objective-C and exposed to JavaScript in React Native.
But you don't need to write native code yourself in most cases — the community has already
created native wrappers via libraries.
🔷 Most Common Native Modules You’ll Use
✅ 1. Permissions – Ask for access to camera, location, etc.
📦 Install:
npm install react-native-permissions
✅ Setup for Android/iOS required (edit AndroidManifest.xml or Info.plist)
✅ Usage:
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
const requestCamera = async () => {
const result = await request(
Platform.OS === 'android'
? PERMISSIONS.ANDROID.CAMERA
: PERMISSIONS.IOS.CAMERA
);
if (result === RESULTS.GRANTED) {
console.log('Camera permission granted');
} else {
console.log('Camera permission denied');
};
✅ 2. Camera Access
📦 Library: react-native-image-picker
npm install react-native-image-picker
✅ Pick an image from gallery or camera:
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
launchCamera({}, (response) => {
if (!response.didCancel) {
console.log(response.assets[0].uri); // image path
});
✅ 3. Location Access
📦 Library: @react-native-community/geolocation
npm install @react-native-community/geolocation
✅ Usage:
import Geolocation from '@react-native-community/geolocation';
Geolocation.getCurrentPosition(
(position) => {
console.log(position.coords.latitude, position.coords.longitude);
},
(error) => {
console.log(error.message);
},
{ enableHighAccuracy: true, timeout: 15000 }
);
✅ You must request permission using react-native-permissions first.
✅ 4. Vibration / Toast / Clipboard
● Vibration: vibrate the device
import { Vibration } from 'react-native';
Vibration.vibrate(500); // vibrate for 500ms
● ToastAndroid: show native toast (Android only)
import { ToastAndroid } from 'react-native';
ToastAndroid.show("Hello!", ToastAndroid.SHORT);
● Clipboard: copy/paste
import * as Clipboard from 'expo-clipboard';
await Clipboard.setStringAsync('Copied text');
✅ 5. Linking Native Apps (Browser, Dialer, etc.)
import { Linking } from 'react-native';
// Open browser
Linking.openURL('https://google.com');
// Call a phone number
Linking.openURL('tel:1234567890');
// Send email
Linking.openURL('mailto:[email protected]');
✅ 6. Share Functionality
import { Share } from 'react-native';
Share.share({
message: 'Check out this awesome app!',
});
📱 Real-world Examples
Feature Native Module/Library
Camera react-native-image-picker
Access
Permissions react-native-permissions
Geolocation @react-native-community/geolocation
Notifications react-native-push-notification
File Access react-native-fs
Device Info react-native-device-info
🧠 Summary Table
Module Purpose
Permissions Request camera, location, etc.
Image Picker Take/select photos from device
Geolocation Get user's current location
Linking Open URLs, phone dialer, email
Vibration Vibrate phone
ToastAndroid Native Android toast message
Clipboard Copy/paste text
Share Share message via phone apps
🛠 Mini Project Suggestion
Create a Profile Uploader App:
Ask for camera permission
Open image picker
Display selected profile picture
Store image path in AsyncStorage
✅ Chapter 11: Debugging & Tools in
React Native
🔍 1. Debugging Basics in React Native
✅ Enable Debug Mode
● Shake the device or emulator → Open Developer Menu
● Options:
○ Debug (connects to Chrome/Flipper)
○ Enable Live Reload
○ Enable Hot Reloading
✅ Use console.log()
Basic but powerful:
console.log("User info", user);
console.warn("Warning occurred");
console.error("Something broke");
These logs appear:
● In the Metro bundler terminal
● Or in Flipper / Chrome devtools
🔷 2. Flipper (Visual Debugging Tool for React Native)
Flipper is Facebook's dev tool that works natively with React Native apps.
📦 Setup
1. Install Flipper: https://fbflipper.com
2. Add React Native plugin:
npm install --save react-native-flipper
Works best with React Native CLI apps (not Expo).
🔍 What Flipper Can Do:
● View app logs
● Inspect Redux state
● Monitor network requests
● Debug layouts
● View AsyncStorage
🔷 3. React Developer Tools
React DevTools lets you inspect your component tree.
✅ Setup:
npm install -g react-devtools
Run:
react-devtools
Then, in the developer menu on your app → enable "Debug with Chrome"
This connects your app to DevTools!
🔷 4. Redux DevTools (for state debugging)
If you're using Redux or Redux Toolkit, this tool is game-changing.
✅ Setup:
1. Install Redux DevTools extension in Chrome
2. Setup in store:
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: { yourReducer },
devTools: true,
});
You can now:
● Time travel through state
● See every dispatched action
● View and edit state live
🔷 5. Network Request Debugging
✅ Axios Interceptors
Log every request or response:
axios.interceptors.request.use((config) => {
console.log('Request:', config);
return config;
});
axios.interceptors.response.use((response) => {
console.log('Response:', response);
return response;
});
✅ With Flipper:
● Use the Network plugin
● Shows live API requests, headers, response status
🔷 6. Error Tracking Tools (for production)
Use these tools in real apps to catch crashes & errors:
Tool Purpose
Sentry Full crash reporting
Bugsnag Crash analytics
Firebase Crash logs + performance
Crashlytics tracking
📦 Example (Sentry):
npm install @sentry/react-native
🔷 7. Performance Monitoring Tools
● why-did-you-render: Detects unnecessary re-renders
● React.memo, useMemo, useCallback — used with DevTools to optimize
🧠 Summary Table
Tool Purpose
console.log() Print data to terminal/console
React DevTools Inspect component tree
Flipper Visual debugger (logs, network,
storage)
Redux DevTools Inspect & time-travel app state
Axios Interceptors Debug API requests/responses
Sentry/Crashlytics Monitor real-time crashes in production
🛠 Practice Task
Create a test screen:
● Add a TextInput and Button
● Add console.log() for each interaction
● Add a fake Axios call → view logs in Flipper
● Setup Flipper and inspect state (if using Redux)
Awesome, Preeti! You're now entering 🚀 Chapter 12: Performance Optimization — a crucial
skill for making sure your React Native apps run fast, stay smooth, and give users a great
experience, especially on lower-end devices.
✅ Chapter 12: Performance Optimization
in React Native
We’ll cover:
● Reducing unnecessary re-renders
● Optimizing FlatList
● Memoization (with useMemo, useCallback, React.memo)
● Animation performance
● Reducing app size
🔷 1. Avoid Unnecessary Re-renders
React Native re-renders a component when its state or props change.
But re-rendering deep component trees or large lists repeatedly slows your app.
✅ Use React.memo()
Prevents re-render unless props actually change.
const MyComponent = React.memo(({ name }) => {
console.log("Rendered");
return <Text>Hello {name}</Text>;
});
Use this for reusable child components that receive same props often.
🔷 2. useCallback() and useMemo()
✅ useCallback() — Memoize functions
const handlePress = useCallback(() => {
console.log("Button pressed");
}, []);
Prevents the function from being re-created on every render.
✅ useMemo() — Memoize calculated values
const total = useMemo(() => {
return cart.reduce((sum, item) => sum + item.price, 0);
}, [cart]);
Only recalculates if cart changes.
🔷 3. FlatList Optimization
Large scrollable lists can lag if not handled properly.
✅ Use FlatList properly:
<FlatList
data={myData}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
initialNumToRender={10} // First render count
maxToRenderPerBatch={5} // Batch render limit
windowSize={10} // Number of screens to render offscreen
removeClippedSubviews={true} // Unmount invisible items (Android)
/>
✅ Also:
● Use getItemLayout for fixed height items
● Avoid inline functions in renderItem
🔷 4. Avoid Anonymous Inline Functions
Avoid this:
<Button onPress={() => doSomething()} />
Prefer:
const handlePress = () => doSomething();
<Button onPress={handlePress} />
🔷 5. Optimize Images
Large images can slow down render and increase memory usage.
✅ Use:
● Proper image sizes (don’t load 5000x5000px)
● resizeMode="contain" or "cover"
● Cache images with:
○ react-native-fast-image (recommended)
npm install react-native-fast-image
🔷 6. Use Lazy Loading / Code Splitting
Split screens or components and load only when needed using React.lazy or
navigation-based splitting.
🔷 7. Reduce App Size
✅ Techniques:
● Use Proguard for Android
● Remove unused assets
● Minify JS
● Use vector icons instead of heavy PNGs
● Split builds by architecture (arm64, x86)
🔷 8. Optimize Animations
React Native’s default animations are fine, but for high performance:
✅ Use:
● Reanimated (react-native-reanimated)
● LayoutAnimation for UI transitions
import { LayoutAnimation } from 'react-native';
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
🔷 9. Avoid Deep State Updates
Instead of deeply nested objects like:
user.profile.avatar.url
Flatten structure:
{ userName, avatarUrl }
Makes state updates faster and predictable.
🔷 10. Production Build Optimizations
✅ Android:
● Enable hermes engine
● Use release build:
npx react-native run-android --variant=release
✅ iOS:
● Archive build using Xcode with Release configuration
🧠 Summary Table
Optimization Area Technique
Re-renders React.memo, useCallback,
useMemo
FlatList Batch rendering, remove
subviews
Large Lists VirtualizedList, getItemLayout
Image Loading Optimize size, use FastImage
Animations Reanimated, LayoutAnimation
Functions Avoid inline, memoize
App Size Proguard, minify, Hermes
State Updates Keep state flat
🛠 Practice Task
Create a Product List App:
● Use FlatList with keyExtractor, getItemLayout
● Use React.memo() for ProductCard component
● Use useMemo() to calculate cart total
● Use FastImage for optimized image loading
📲 Chapter 13: Build & Deployment in
React Native
This chapter helps you package your app for release, add a splash screen, custom icon,
and deploy it to Play Store (Android) or App Store (iOS).
✅ Overview of What You’ll Learn
1. Android Build Process
2. iOS Build Process
3. Splash Screen
4. App Icon
5. Versioning
6. Generating APK / AAB
7. Signing & Publishing
8. Environment Variables
9. OTA Updates (Bonus)
🔶 1. Android Build Process (React Native CLI)
🔧 Development Build
npx react-native run-android
Runs the app in debug mode.
📦 Release Build (for Play Store)
cd android
./gradlew assembleRelease
➡️ Output:
android/app/build/outputs/apk/release/app-release.apk
🔶 2. iOS Build Process
macOS & Xcode required
npx react-native run-ios
For release build:
● Open ios/YourApp.xcworkspace in Xcode
● Choose device → Archive → Distribute via App Store
🔶 3. Splash Screen
📦 Install:
npm install react-native-splash-screen
⚙️ Setup (Android):
● Edit styles.xml, MainActivity.java
● Show/hide splash via SplashScreen.show() and SplashScreen.hide()
⚙️ Setup (iOS):
● Use LaunchScreen.storyboard in Xcode
● Link it with react-native-splash-screen
🧠 You can also use react-native-bootsplash (recommended)
🔶 4. App Icon
Use tool: https://easyappicon.com/
📦 Replace:
● Android: android/app/src/main/res/mipmap-*
● iOS: Assets.xcassets/AppIcon.appiconset
🔶 5. Versioning
📌 Android:
In android/app/build.gradle
versionCode 2
versionName "1.0.1"
📌 iOS:
In ios/YourApp/Info.plist:
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<key>CFBundleVersion</key>
<string>2</string>
🔶 6. Generating APK / AAB (Android App Bundle)
Google recommends AAB now.
📦 For APK:
cd android
./gradlew assembleRelease
➡️ APK in:
app/build/outputs/apk/release/app-release.apk
📦 For AAB:
./gradlew bundleRelease
➡️ AAB in:
app/build/outputs/bundle/release/app-release.aab
AAB is uploaded to Google Play → it auto-generates optimized APKs
🔶 7. App Signing (Important for Play Store)
Generate Keystore:
keytool -genkey -v -keystore my-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048
-validity 10000
Move keystore to:
android/app/my-key.keystore
Add in gradle.properties:
MYAPP_UPLOAD_STORE_FILE=my-key.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
MYAPP_UPLOAD_STORE_PASSWORD=*****
MYAPP_UPLOAD_KEY_PASSWORD=*****
Update build.gradle with signing config.
🔶 8. Upload to Play Store / App Store
Android:
1. Create account at https://play.google.com/console
2. Pay $25
3. Upload .aab
4. Add app details, screenshots, content rating
5. Submit for review
iOS:
1. Register as Apple Developer ($99/year)
2. Archive build in Xcode
3. Upload via Transporter or Xcode
4. Submit to App Store Connect
🔶 9. Environment Variables
Use .env files for secrets like API keys
📦 Install:
npm install react-native-dotenv
✅ Example:
API_URL=https://api.example.com
In JS:
import { API_URL } from '@env';
🔶 10. OTA Updates (Optional, Bonus)
Use CodePush to push updates without Play Store resubmission.
📦 Install:
npm install react-native-code-push
➡️ Push JavaScript updates to users on app open
➡️ Saves time & enables fast fixes
🧠 Summary Table
Task Tool / Command
Build Android ./gradlew assembleRelease (APK)
Build AAB (Play Store) ./gradlew bundleRelease
Build iOS (Xcode) Archive + App Store Connect
Splash Screen react-native-splash-screen or bootsplash
App Icon Replace mipmap-* & Assets.xcassets
App Signing keytool + gradle.properties
Upload Google Play Console / App Store Connect
Env Vars react-native-dotenv
OTA Updates react-native-code-push
🛠 Final Project Suggestion
Build a Production-ready App with:
● Custom splash screen & icon
● Securely saved login token in AsyncStorage
● .env variables for API
● Build a signed .aab file
● Submit to Play Store beta