React Native

Created
TypeLibrary
LanguageJavascript
Last Edit

Introduction

React Native Basic

What is it

Components

JSX components will be compiled to their native views, but not Javascript logic/code as its run as a uncompiled JavaScript thread hosted by react native.

Project Setup

Expo

Managed app development

npx create-expo-app@latest <project-name> 

Setup Dev Environment

Set up your environment
Learn how to set up your development environment to start building with Expo.
https://docs.expo.dev/get-started/set-up-your-environment/?platform=ios&device=simulated&mode=development-build&buildEnv=local

Basics

Core Components

Core Components and APIs · React Native
React Native provides a number of built-in Core Components ready for you to use in your app. You can find them all in the left sidebar (or menu above, if you are on a narrow screen). If you're not sure where to get started, take a look at the following categories:
https://reactnative.dev/docs/components-and-apis

Styling

🚫

No CSS available for styling

Written in JS, based on CSS syntax → Only subset of properties supported.

Style · React Native
With React Native, you style your application using JavaScript. All of the core components accept a prop named style. The style names and values usually match how CSS works on the web, except names are written using camel casing, e.g. backgroundColor rather than background-color.
https://reactnative.dev/docs/style

Inline Styles

<Text style={{margin:  16, border: '1px solid'}}> Hello World </Text>
<Text style={{margin:  16, borderWidth: 1, borderColor: 'red'}}> Hello World </Text>
StyleSheet Objects

import { StyleSheet} from "react-native";

export default function App() {
	return (
		<View style={styles.container}>
			<Text>Hello World</Text>
			<StatusBar style="auto" />
		</View>
	);
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: "#fff",
		alignItems: "center",
		justifyContent: "center",
	},
});

Color

Color Reference · React Native
Components in React Native are styled using JavaScript. Color properties usually match how CSS works on the web. General guides on the color usage on each platform could be found below:
https://reactnative.dev/docs/colors
Layouts & Flexbox

Element spacing and positioning in a container.

💡

View component is already a flexbox with default flexDirection as column

Properties

import { StyleSheet, Text, View } from "react-native";

export default function App() {
	return (
		<View style={styles.container}>
			<View
				style={{
					backgroundColor: "red",
					flex: 1,
					justifyContent: "center",
					alignItems: "center",
				}}
			>
				<Text>1</Text>
			</View>
			<View
				style={{
					backgroundColor: "blue",
					flex: 2,
					justifyContent: "center",
					alignItems: "center",
				}}
			>
				<Text>2</Text>
			</View>
			<View
				style={{
					backgroundColor: "green",
					flex: 1,
					justifyContent: "center",
					alignItems: "center",
				}}
			>
				<Text>3</Text>
			</View>
		</View>
	);
}

const styles = StyleSheet.create({
	container: {
		padding: 50,
		flexDirection: "row",
		width: "100%",
		height: 300,
		alignItems: "stretch",
		justifyContent: "center",
	},
});

Here the flex property inside the child view determines how much space the component will occupy out of available space in parent.

Navigation

Package

npm install @react-navigation/native

Expo dependencies

npx expo install react-native-screens react-native-safe-area-context

Usage

import { NavigationContainer } from '@react-navigation/native';

<NavigationContainer><App/></NavigationContainer>

Navigators

https://reactnavigation.org/docs/stack-navigator#

Native Stack Implementation

Wrap stack screen in container and pass required screen as prop to stack.screen

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();


<NavigationContainer>
				<Stack.Navigator>
					<Stack.Screen name="GettingStarted" component={GettingStarted} />
					<Stack.Screen name="SignIn" component={SignIn} />
				</Stack.Navigator>
			</NavigationContainer>
💡

Out of the box, the top-most screen (i.e. the first child inside of <Stack.Navigator>) is used as the default/initial screen.

Or you can set default by:

<Stack.Navigator initialRouteName="SignIn">

Navigate

OPTION 1

Screens set as component for stack.screen will have navigation prop set, which can be used to navigate w.r.t name of screen sett in stack.screen.


const GettingStarted = ({ navigation }) => {
	const pressHandler = () => {
		navigation.navigate('SignIn');
	};

	return (
		<View style={styles.buttonContainer}>
			<GSButton onPress={pressHandler} />
		</View>
	);
};

OPTION 2

Use hook: useNavigation

import { useNavigation } from '@react-navigation/native';

const GSButton = () => {
	const navigation = useNavigation();

	const pressHandler = () => {
		navigation.navigate('OTP_Get');
	};

	return (
		<Button mode="contained" onPress={pressHandler}>
			Get Started
		</Button>
	);
};
Navigation Hook Options
navigation.setOptions({
	title: condition ? 'Title A' : 'Title B',
})

navigation.goBack();
MethodDescription
navigate(name, params)Navigate to a screen in the stack. You can pass parameters.
goBack()Go back to the previous screen.
push(name, params)Push a new route to the stack, even if it’s the same as the current one.
replace(name, params)Replace the current route with a new one.
pop(count)Go back by a certain number of screens.
popToTop()Go back to the first screen in the stack.
reset(config)Reset the navigation state. Useful for authentication flows.
setParams(params)Update the route's params.
dispatch(action)Send a custom navigation action.

Nested Navigators

Stack & Bottom Tabs In One
✅ Option 1: Bottom Tabs as the main navigator, with each tab having its own Stack

// App.js or Navigation.js
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';

const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();

// Example screens
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
import SettingsScreen from './screens/SettingsScreen';

// Stack for Home Tab
function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

// Main Tab Navigator
export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="HomeTab" component={ } />
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}


✅ Option 2: Stack as the main navigator, with Bottom Tabs inside one of the screens

function Tabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Main" component={Tabs} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Protected Navigation
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { NavigationContainer } from '@react-navigation/native';

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import { checkPersistentData } from './app/store/auth/auth-methods';

//? Auth Screens
import GettingStartedScreen from './app/screens/Auth/GettingStartedScreen';
import OtpGetScreen from './app/screens/Auth/OtpGetScreen';
import OtpVerifyScreen from './app/screens/Auth/OtpVerifyScreen';

//? Protected Screens
import HomeScreen from './app/screens/Home/HomeScreen';

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

const AuthStack = () => {
	return (
		<Stack.Navigator>
			<Stack.Screen
				name="GettingStarted"
				component={GettingStartedScreen}
				// options={{
				// 	headerShown: false,
				// }}
			/>
			<Stack.Screen
				name="OTP_Get"
				component={OtpGetScreen}
				// options={{
				// 	headerShown: false,
				// }}
			/>
			<Stack.Screen
				name="OTP_Verify"
				component={OtpVerifyScreen}
				// options={{
				// 	headerShown: false,
				// }}
			/>
		</Stack.Navigator>
	);
};

const ProtectedTabs = () => {
	return (
		<Tab.Navigator>
			<Tab.Screen
				name="Home"
				component={HomeScreen}
				options={{
					title: 'Home',
				}}
			/>
			<Tab.Screen
				name="My_Courses"
				component={HomeScreen}
				options={{
					title: 'My Courses',
				}}
			/>
			<Tab.Screen
				name="Profile"
				component={HomeScreen}
				options={{
					title: 'Profile',
				}}
			/>
		</Tab.Navigator>
	);
};

const Navigation = () => {
	const dispatch = useDispatch();
	const auth = useSelector((state) => state.auth);

	useEffect(() => {
		dispatch(checkPersistentData());
	}, []);

	return <NavigationContainer>{auth.isLoggedIn ? <ProtectedTabs /> : <AuthStack />}</NavigationContainer>;
};

export default Navigation;

HTTP Requests

Loading Indicator

Loading Overlay

import {View, ActivityIndicator, StyleSheet} from 'react-native';

const LoadingOverlay = () => {
	return (
		<View style={styles.container}>
			<ActivityIndicator size="large" color="white" />
		</View>
	);
}

export default LoadingOverlay;

const styles = StyleSheet.create({
	container: {
		flex: 1, 
		justifyContent: 'center',
		alignItems: 'center',
		padding: 24,
		backgroundColor: 'grey',
	},
});