DEV Community

Cover image for Mastering React Native with TypeScript: From Basics to Brilliance - Part 3
Rushikesh Pandit
Rushikesh Pandit

Posted on

Mastering React Native with TypeScript: From Basics to Brilliance - Part 3

React Native has come a long way, and with the latest versions offering improved performance and TypeScript-first development, it’s a great time to dive into building robust apps with navigation and API communication in mind.
In this article, we’ll explore:

  • Setting up React Navigation in a TypeScript project
  • Working with Stacks and Tabs
  • Managing API calls with axios and useEffect
  • Handling loading, error, and data states
  • Bonus: Tips for organizing your codebase!

Prerequisites

  • Node.js 18+
  • React Native CLI or Expo (we'll go with bare React Native here)
  • React Native 0.76+
  • TypeScript
  • Basic understanding of React Native components

Setup React Navigation

First, install the required dependencies:

npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context react-native-gesture-handler react-native-reanimated
npx pod-install
Enter fullscreen mode Exit fullscreen mode

Then install the stack and bottom tab navigators:

npm install @react-navigation/native-stack @react-navigation/bottom-tabs
Enter fullscreen mode Exit fullscreen mode

Update babel.config.js for reanimated (if not Expo):

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['react-native-reanimated/plugin'],
};
Enter fullscreen mode Exit fullscreen mode

Create Navigation Structure

navigation/RootNavigator.tsx

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen';
import DetailsScreen from '../screens/DetailsScreen';

export type RootStackParamList = {
  Home: undefined;
  Details: { userId: number };
};

const Stack = createNativeStackNavigator<RootStackParamList>();

const RootNavigator = () => (
  <NavigationContainer>
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  </NavigationContainer>
);

export default RootNavigator;
Enter fullscreen mode Exit fullscreen mode

Create Screen Components for Home Screen

screens/HomeScreen.tsx

import React, { useEffect, useState } from 'react';
import { View, Text, Button, FlatList, ActivityIndicator } from 'react-native';
import axios from 'axios';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { RootStackParamList } from '../navigation/RootNavigator';

type Props = NativeStackScreenProps<RootStackParamList, 'Home'>;

interface User {
  id: number;
  name: string;
}

const HomeScreen: React.FC<Props> = ({ navigation }) => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    axios.get<User[]>('https://jsonplaceholder.typicode.com/users')
      .then(response => setUsers(response.data))
      .catch(err => setError(err.message))
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Error: {error}</Text>;

  return (
    <FlatList
      data={users}
      keyExtractor={item => item.id.toString()}
      renderItem={({ item }) => (
        <View style={{ padding: 10 }}>
          <Text>{item.name}</Text>
          <Button
            title="View Details"
            onPress={() => navigation.navigate('Details', { userId: item.id })}
          />
        </View>
      )}
    />
  );
};

export default HomeScreen;
Enter fullscreen mode Exit fullscreen mode

Create Screen Components for Detail Screen

screens/DetailsScreen.tsx

import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import axios from 'axios';
import { RootStackParamList } from '../navigation/RootNavigator';

type Props = NativeStackScreenProps<RootStackParamList, 'Details'>;

interface UserDetail {
  id: number;
  name: string;
  email: string;
  phone: string;
}

const DetailsScreen: React.FC<Props> = ({ route }) => {
  const { userId } = route.params;
  const [user, setUser] = useState<UserDetail | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    axios.get<UserDetail>(`https://jsonplaceholder.typicode.com/users/${userId}`)
      .then(response => setUser(response.data))
      .finally(() => setLoading(false));
  }, [userId]);

  if (loading) return <ActivityIndicator />;
  if (!user) return <Text>No user found</Text>;

  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 18 }}>{user.name}</Text>
      <Text>{user.email}</Text>
      <Text>{user.phone}</Text>
    </View>
  );
};

export default DetailsScreen;
Enter fullscreen mode Exit fullscreen mode

Organize API Layer (Optional but Recommended)

Create a file api/client.ts:

import axios from 'axios';

const client = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/',
  timeout: 5000,
});

export default client;
Enter fullscreen mode Exit fullscreen mode

Then import and use client.get() instead of axios.get().

Project Structure Suggestion

/src
  /navigation
    RootNavigator.tsx
  /screens
    HomeScreen.tsx
    DetailsScreen.tsx
  /api
    client.ts
  /types
    index.ts
App.tsx
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

  • React Navigation’s TypeScript support makes route safety a breeze.
  • Centralizing API calls helps scale and debug faster.
  • Handling loading/error/data states improves user experience.
  • Organize your folders early—it pays off later!

That's it for today. In the next part of this series, we’ll explore advanced topics like redux toolkit and it's implementation.

Feel free to reach out to me if you have any questions or need assistance.
LinkedIn: https://www.linkedin.com/in/rushikesh-pandit-646834100/
GitHub: https://github.com/rushikeshpandit
Portfolio: https://www.rushikeshpandit.in

#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity

Top comments (0)