12.1 Layout & Navigation

In this module we will look focus on routing & navigation (opens new window), or "moving between screens" in your mobile app. But first we should address an important layout issue.

# Safe Area Context

The core React Native project provides a <SafeAreaView /> component to help keep you application content from being obscured by sensor notches or status bars. However, it only works with iOS 11+. Fortunately, there is a community developed package that provides consistent support across all iOS, Android, and Web target deployments. It is called react-native-safe-area-context (opens new window) and Expo provides an optimized installer ...

expo install react-native-safe-area-context
1

As its name implies this module uses React's Context API and you will need to wrap your top App level JSX component with the <SafeAreaProvider> component imported from react-native-safe-area-context. Then wrap each of your view (screen) components with the <SafeAreaView> component imported from react-native-safe-area-context – not the one from react-native.

# With React Navigation Header

When using the <SafeAreaView> component with React Navigation's default header component, you will see extra unwanted padding below the header. To correct this, set the edges prop on the <SafeAreaView> component to exclude the top edge of the device. Just list the sides that you want to go all the way to the edge of the screen.

import { SafeAreaView } from 'react-native-safe-area-context';

export default function Demo() {
  return (
    <SafeAreaView style={{ flex: 1 }} edges={['right', 'bottom', 'left']}>
      {/* rest of your JSX content */}
    </SafeAreaView>
  );
}
1
2
3
4
5
6
7
8
9

# Routing & Navigation

React Navigation (opens new window) is the most popular navigation library in the React Native ecosystem and it is maintained by Expo, so it's guaranteed to work great in your Expo managed apps.

There are three common modes for mobile application navigation: stacks, tabs, and drawers. The React Navigation library supports all three of these modes and they can be used in combination (see nested navigation (opens new window)).

Note: There is another library alternative called React-Native-Navigation. You can use this if you used React Native CLI to create your project. However, React Navigation is installed along with Expo.

# Install dependencies

The React Navigation library is divided into several modules. A core module and separate modules for each routing mode. It also relies on some peer dependencies. Start by installing the core library.

yarn add @react-navigation/native
1

Now add the peer dependencies.

expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
1

After this you need to add the module for the type of navigation you want to use in your app. For our lab demo, we will use the familiar stack navigation - this works similarly to how the history API works in the browser. The stack is like an array of recently viewed pages/components.

yarn add @react-navigation/stack
1

# Hello React Navigation

Lets build a very simple React Native app with Expo and React Navigation. To keep things simple, it will have just three pages and very little content.

# Initialize a new project

expo init hello-nav
1

Then add the React Navigation modules as per the instructions above.

# Create three simple page components

// HomeScreen.js
import React from 'react';
import { View, Text } from 'react-native';

export default function HomeScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
// AboutScreen.js
import React from 'react';
import { View, Text } from 'react-native';

export default function AboutScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>About Screen</Text>
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11
// ContactScreen.js
import React from 'react';
import { View, Text } from 'react-native';

export default function ContactScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Contact Screen</Text>
    </View>
  );
}
1
2
3
4
5
6
7
8
9
10
11

# The NavigationContainer

Similar to the <BrowserRouter> component that we used from React Router, the <NavigationContainer> component provides the navigation state management context and usually wraps the main App component's JSX.

// /App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';

function App() {
  return <NavigationContainer></NavigationContainer>;
}

export default App;
1
2
3
4
5
6
7
8
9

Important note: all your initial top-level screens defined in the StackNavigator or your TabBottomNavigator will be loaded when your app loads.

# Create a stack navigator

To use the stack navigator import the createStackNavigator function. When invoked, it returns on object with two properties containing React components: Screen and Navigator.

The routes are defined by placing the Screen components as children to the Navigator component in your JSX markup.

Update the App.js component to look like this ...




 
 

 




 
 
 






// /App.js updated
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './components/HomeScreen';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

OK, now add routes for the other two screens.

Solution: Try yourself before you look




 
 








 
 







import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './components/HomeScreen';
import AboutScreen from './components/AboutScreen';
import ContactScreen from './components/ContactScreen';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="About" component={AboutScreen} />
        <Stack.Screen name="Contact" component={ContactScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Header Options

The route name is used as the page title that appears in the header by default. If you want to customize it, you can add an options prop.

<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Hello' }} />
1

You can set the background style and text colour for the header using the headerStyle and headerTintColor props.




 
 
 
 
 


<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{
    title: 'Hello',
    headerStyle: { backgroundColor: 'indigo' },
    headerTintColor: 'white',
  }}
/>
1
2
3
4
5
6
7
8
9

Remember to adjust the status bar text

You can use the React Native StatusBar (opens new window) component's barStyle prop to adjust the system status text to light or dark or auto or inverted to fit your app's colour scheme. e.g.

<StatusBar barStyle="light" />
1

# Default Header Options

It is great to be able to change individual header display properties, but most of the time you will want a consistent look across your application. Rather than repeating the config options on every screen, you can set the default options to apply to all screens using the screenOptions prop on the Stack.Navigator component. e.g.

<Stack.Navigator
  screenOptions={{
    headerStyle: {backgroundColor: 'indigo'},
    headerTintColor: 'white'
  }}
  initialRouteName="Home"
>
1
2
3
4
5
6
7

Any default settings can be overridden by the options prop on an individual Stack.Screen component as needed.

# How to move between screens

Each screen component receives two navigator related objects as props: navigation, and route. Here is the Route Prop Reference (opens new window) and Navigation Prop Reference (opens new window).

In order to change screens you need to tell the navigation object which new screen to display using the navigation.navigate() method. This would typically be in an onPress event handler. The first argument to the navigate() method is the name (as a string) of a screen defined in the Stack.Navigator - in our example that is in the App component.

<Button title="Read more about us" onPress={() => props.navigation.navigate('About')} />
<Button title="Contact us" onPress={() => props.navigation.navigate('Contact')} />
1
2
# Going back

There are several options here.

  1. The header will automatically add a < Back button if the user is not on the first page of the stack.
  2. The hardware back button on Android devices is automatically configured to go back one step in the stack.
  3. You can programmatically pop the last screen off the stack with navigation.goBack() in an onPress handler.
  4. You can navigate directly to any earlier screen in the stack (skipping intermediate screens) by using the navigation.navigate() method. e.g.
<Button title="Home" onPress={() => props.navigation.navigate('Home')}>
1

Here is a list of the Navigation Events (opens new window) with an example of how to add your own listener inside a useEffect Hook.

Here is a guide (opens new window) for adding the functionality of preventing the user from going back to the previous screen. For example, they were filling out a form and you want to confirm leaving the screen.

# Passing route params

If you need to pass parameters, like an object id, to a screen component then you can pass an object as the second argument with key:value pairs.

<Button title="Read book review" onPress={() => props.navigation.navigate('Review', {id: book.id})}>
1

Then in the screen component you can access these parameters via the props.route.params object. So, for the book review example above, the screen component might look like this ...

import React from 'react';
import { ScrollView, Text, View, StyleSheet } from 'react-native';

export default function BookReviewScreen({ route }) {
  const [book, setBook] = React.useState({});

  React.useEffect(() => {
    // fetch book using route.params.id
  }, [route.params.id]);

  return {
    /* some JSX */
  };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Do not pass complex objects

The route.params are meant to pass simple key value pairs. Think of passing URL parameter. This allows your app to support sharing deep links for higher user engagement.

# Lab Exercise

It is time to practice what you have learned. Build a simple two page Summary/Detail application. The first page will use the Expo FlatList Ref (opens new window) or RN FlatList Ref (opens new window) component to display a list of movie titles and the year it was released. Tapping on a movie list item should navigate to a new page displaying the detailed information for that one movie.

You will need the TouchableOpacity (opens new window) component OR the newer Pressable (opens new window) component to make the list items something that the user can interact with (pressable).

You will need to pass the movie episode_id as a route parameter.

You will need to create a context provider for the movie data, so that it is available to both the movie list screen and the movie detail screen.

Don't worry about fetching data from an API for this exercise. Simply import the array of movie data from this module.

movieData.js
export const movieData = [
  {
    title: 'A New Hope',
    episode_id: 4,
    opening_crawl:
      "It is a period of civil war.\r\nRebel spaceships, striking\r\nfrom a hidden base, have won\r\ntheir first victory against\r\nthe evil Galactic Empire.\r\n\r\nDuring the battle, Rebel\r\nspies managed to steal secret\r\nplans to the Empire's\r\nultimate weapon, the DEATH\r\nSTAR, an armored space\r\nstation with enough power\r\nto destroy an entire planet.\r\n\r\nPursued by the Empire's\r\nsinister agents, Princess\r\nLeia races home aboard her\r\nstarship, custodian of the\r\nstolen plans that can save her\r\npeople and restore\r\nfreedom to the galaxy....",
    director: 'George Lucas',
    producer: 'Gary Kurtz, Rick McCallum',
    release_date: '1977-05-25',
    characters: [
      'http://swapi.dev/api/people/1/',
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/4/',
      'http://swapi.dev/api/people/5/',
      'http://swapi.dev/api/people/6/',
      'http://swapi.dev/api/people/7/',
      'http://swapi.dev/api/people/8/',
      'http://swapi.dev/api/people/9/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/12/',
      'http://swapi.dev/api/people/13/',
      'http://swapi.dev/api/people/14/',
      'http://swapi.dev/api/people/15/',
      'http://swapi.dev/api/people/16/',
      'http://swapi.dev/api/people/18/',
      'http://swapi.dev/api/people/19/',
      'http://swapi.dev/api/people/81/'
    ],
    planets: [
      'http://swapi.dev/api/planets/1/',
      'http://swapi.dev/api/planets/2/',
      'http://swapi.dev/api/planets/3/'
    ],
    starships: [
      'http://swapi.dev/api/starships/2/',
      'http://swapi.dev/api/starships/3/',
      'http://swapi.dev/api/starships/5/',
      'http://swapi.dev/api/starships/9/',
      'http://swapi.dev/api/starships/10/',
      'http://swapi.dev/api/starships/11/',
      'http://swapi.dev/api/starships/12/',
      'http://swapi.dev/api/starships/13/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/4/',
      'http://swapi.dev/api/vehicles/6/',
      'http://swapi.dev/api/vehicles/7/',
      'http://swapi.dev/api/vehicles/8/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/3/',
      'http://swapi.dev/api/species/4/',
      'http://swapi.dev/api/species/5/'
    ],
    created: '2014-12-10T14:23:31.880000Z',
    edited: '2014-12-20T19:49:45.256000Z',
    url: 'http://swapi.dev/api/films/1/'
  },
  {
    title: 'The Empire Strikes Back',
    episode_id: 5,
    opening_crawl:
      'It is a dark time for the\r\nRebellion. Although the Death\r\nStar has been destroyed,\r\nImperial troops have driven the\r\nRebel forces from their hidden\r\nbase and pursued them across\r\nthe galaxy.\r\n\r\nEvading the dreaded Imperial\r\nStarfleet, a group of freedom\r\nfighters led by Luke Skywalker\r\nhas established a new secret\r\nbase on the remote ice world\r\nof Hoth.\r\n\r\nThe evil lord Darth Vader,\r\nobsessed with finding young\r\nSkywalker, has dispatched\r\nthousands of remote probes into\r\nthe far reaches of space....',
    director: 'Irvin Kershner',
    producer: 'Gary Kurtz, Rick McCallum',
    release_date: '1980-05-17',
    characters: [
      'http://swapi.dev/api/people/1/',
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/4/',
      'http://swapi.dev/api/people/5/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/13/',
      'http://swapi.dev/api/people/14/',
      'http://swapi.dev/api/people/18/',
      'http://swapi.dev/api/people/20/',
      'http://swapi.dev/api/people/21/',
      'http://swapi.dev/api/people/22/',
      'http://swapi.dev/api/people/23/',
      'http://swapi.dev/api/people/24/',
      'http://swapi.dev/api/people/25/',
      'http://swapi.dev/api/people/26/'
    ],
    planets: [
      'http://swapi.dev/api/planets/4/',
      'http://swapi.dev/api/planets/5/',
      'http://swapi.dev/api/planets/6/',
      'http://swapi.dev/api/planets/27/'
    ],
    starships: [
      'http://swapi.dev/api/starships/3/',
      'http://swapi.dev/api/starships/10/',
      'http://swapi.dev/api/starships/11/',
      'http://swapi.dev/api/starships/12/',
      'http://swapi.dev/api/starships/15/',
      'http://swapi.dev/api/starships/17/',
      'http://swapi.dev/api/starships/21/',
      'http://swapi.dev/api/starships/22/',
      'http://swapi.dev/api/starships/23/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/8/',
      'http://swapi.dev/api/vehicles/14/',
      'http://swapi.dev/api/vehicles/16/',
      'http://swapi.dev/api/vehicles/18/',
      'http://swapi.dev/api/vehicles/19/',
      'http://swapi.dev/api/vehicles/20/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/3/',
      'http://swapi.dev/api/species/6/',
      'http://swapi.dev/api/species/7/'
    ],
    created: '2014-12-12T11:26:24.656000Z',
    edited: '2014-12-15T13:07:53.386000Z',
    url: 'http://swapi.dev/api/films/2/'
  },
  {
    title: 'Return of the Jedi',
    episode_id: 6,
    opening_crawl:
      'Luke Skywalker has returned to\r\nhis home planet of Tatooine in\r\nan attempt to rescue his\r\nfriend Han Solo from the\r\nclutches of the vile gangster\r\nJabba the Hutt.\r\n\r\nLittle does Luke know that the\r\nGALACTIC EMPIRE has secretly\r\nbegun construction on a new\r\narmored space station even\r\nmore powerful than the first\r\ndreaded Death Star.\r\n\r\nWhen completed, this ultimate\r\nweapon will spell certain doom\r\nfor the small band of rebels\r\nstruggling to restore freedom\r\nto the galaxy...',
    director: 'Richard Marquand',
    producer: 'Howard G. Kazanjian, George Lucas, Rick McCallum',
    release_date: '1983-05-25',
    characters: [
      'http://swapi.dev/api/people/1/',
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/4/',
      'http://swapi.dev/api/people/5/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/13/',
      'http://swapi.dev/api/people/14/',
      'http://swapi.dev/api/people/16/',
      'http://swapi.dev/api/people/18/',
      'http://swapi.dev/api/people/20/',
      'http://swapi.dev/api/people/21/',
      'http://swapi.dev/api/people/22/',
      'http://swapi.dev/api/people/25/',
      'http://swapi.dev/api/people/27/',
      'http://swapi.dev/api/people/28/',
      'http://swapi.dev/api/people/29/',
      'http://swapi.dev/api/people/30/',
      'http://swapi.dev/api/people/31/',
      'http://swapi.dev/api/people/45/'
    ],
    planets: [
      'http://swapi.dev/api/planets/1/',
      'http://swapi.dev/api/planets/5/',
      'http://swapi.dev/api/planets/7/',
      'http://swapi.dev/api/planets/8/',
      'http://swapi.dev/api/planets/9/'
    ],
    starships: [
      'http://swapi.dev/api/starships/2/',
      'http://swapi.dev/api/starships/3/',
      'http://swapi.dev/api/starships/10/',
      'http://swapi.dev/api/starships/11/',
      'http://swapi.dev/api/starships/12/',
      'http://swapi.dev/api/starships/15/',
      'http://swapi.dev/api/starships/17/',
      'http://swapi.dev/api/starships/22/',
      'http://swapi.dev/api/starships/23/',
      'http://swapi.dev/api/starships/27/',
      'http://swapi.dev/api/starships/28/',
      'http://swapi.dev/api/starships/29/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/8/',
      'http://swapi.dev/api/vehicles/16/',
      'http://swapi.dev/api/vehicles/18/',
      'http://swapi.dev/api/vehicles/19/',
      'http://swapi.dev/api/vehicles/24/',
      'http://swapi.dev/api/vehicles/25/',
      'http://swapi.dev/api/vehicles/26/',
      'http://swapi.dev/api/vehicles/30/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/3/',
      'http://swapi.dev/api/species/5/',
      'http://swapi.dev/api/species/6/',
      'http://swapi.dev/api/species/8/',
      'http://swapi.dev/api/species/9/',
      'http://swapi.dev/api/species/10/',
      'http://swapi.dev/api/species/15/'
    ],
    created: '2014-12-18T10:39:33.255000Z',
    edited: '2014-12-20T09:48:37.462000Z',
    url: 'http://swapi.dev/api/films/3/'
  },
  {
    title: 'The Phantom Menace',
    episode_id: 1,
    opening_crawl:
      'Turmoil has engulfed the\r\nGalactic Republic. The taxation\r\nof trade routes to outlying star\r\nsystems is in dispute.\r\n\r\nHoping to resolve the matter\r\nwith a blockade of deadly\r\nbattleships, the greedy Trade\r\nFederation has stopped all\r\nshipping to the small planet\r\nof Naboo.\r\n\r\nWhile the Congress of the\r\nRepublic endlessly debates\r\nthis alarming chain of events,\r\nthe Supreme Chancellor has\r\nsecretly dispatched two Jedi\r\nKnights, the guardians of\r\npeace and justice in the\r\ngalaxy, to settle the conflict....',
    director: 'George Lucas',
    producer: 'Rick McCallum',
    release_date: '1999-05-19',
    characters: [
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/11/',
      'http://swapi.dev/api/people/16/',
      'http://swapi.dev/api/people/20/',
      'http://swapi.dev/api/people/21/',
      'http://swapi.dev/api/people/32/',
      'http://swapi.dev/api/people/33/',
      'http://swapi.dev/api/people/34/',
      'http://swapi.dev/api/people/35/',
      'http://swapi.dev/api/people/36/',
      'http://swapi.dev/api/people/37/',
      'http://swapi.dev/api/people/38/',
      'http://swapi.dev/api/people/39/',
      'http://swapi.dev/api/people/40/',
      'http://swapi.dev/api/people/41/',
      'http://swapi.dev/api/people/42/',
      'http://swapi.dev/api/people/43/',
      'http://swapi.dev/api/people/44/',
      'http://swapi.dev/api/people/46/',
      'http://swapi.dev/api/people/47/',
      'http://swapi.dev/api/people/48/',
      'http://swapi.dev/api/people/49/',
      'http://swapi.dev/api/people/50/',
      'http://swapi.dev/api/people/51/',
      'http://swapi.dev/api/people/52/',
      'http://swapi.dev/api/people/53/',
      'http://swapi.dev/api/people/54/',
      'http://swapi.dev/api/people/55/',
      'http://swapi.dev/api/people/56/',
      'http://swapi.dev/api/people/57/',
      'http://swapi.dev/api/people/58/',
      'http://swapi.dev/api/people/59/'
    ],
    planets: [
      'http://swapi.dev/api/planets/1/',
      'http://swapi.dev/api/planets/8/',
      'http://swapi.dev/api/planets/9/'
    ],
    starships: [
      'http://swapi.dev/api/starships/31/',
      'http://swapi.dev/api/starships/32/',
      'http://swapi.dev/api/starships/39/',
      'http://swapi.dev/api/starships/40/',
      'http://swapi.dev/api/starships/41/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/33/',
      'http://swapi.dev/api/vehicles/34/',
      'http://swapi.dev/api/vehicles/35/',
      'http://swapi.dev/api/vehicles/36/',
      'http://swapi.dev/api/vehicles/37/',
      'http://swapi.dev/api/vehicles/38/',
      'http://swapi.dev/api/vehicles/42/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/6/',
      'http://swapi.dev/api/species/11/',
      'http://swapi.dev/api/species/12/',
      'http://swapi.dev/api/species/13/',
      'http://swapi.dev/api/species/14/',
      'http://swapi.dev/api/species/15/',
      'http://swapi.dev/api/species/16/',
      'http://swapi.dev/api/species/17/',
      'http://swapi.dev/api/species/18/',
      'http://swapi.dev/api/species/19/',
      'http://swapi.dev/api/species/20/',
      'http://swapi.dev/api/species/21/',
      'http://swapi.dev/api/species/22/',
      'http://swapi.dev/api/species/23/',
      'http://swapi.dev/api/species/24/',
      'http://swapi.dev/api/species/25/',
      'http://swapi.dev/api/species/26/',
      'http://swapi.dev/api/species/27/'
    ],
    created: '2014-12-19T16:52:55.740000Z',
    edited: '2014-12-20T10:54:07.216000Z',
    url: 'http://swapi.dev/api/films/4/'
  },
  {
    title: 'Attack of the Clones',
    episode_id: 2,
    opening_crawl:
      'There is unrest in the Galactic\r\nSenate. Several thousand solar\r\nsystems have declared their\r\nintentions to leave the Republic.\r\n\r\nThis separatist movement,\r\nunder the leadership of the\r\nmysterious Count Dooku, has\r\nmade it difficult for the limited\r\nnumber of Jedi Knights to maintain \r\npeace and order in the galaxy.\r\n\r\nSenator Amidala, the former\r\nQueen of Naboo, is returning\r\nto the Galactic Senate to vote\r\non the critical issue of creating\r\nan ARMY OF THE REPUBLIC\r\nto assist the overwhelmed\r\nJedi....',
    director: 'George Lucas',
    producer: 'Rick McCallum',
    release_date: '2002-05-16',
    characters: [
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/6/',
      'http://swapi.dev/api/people/7/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/11/',
      'http://swapi.dev/api/people/20/',
      'http://swapi.dev/api/people/21/',
      'http://swapi.dev/api/people/22/',
      'http://swapi.dev/api/people/33/',
      'http://swapi.dev/api/people/35/',
      'http://swapi.dev/api/people/36/',
      'http://swapi.dev/api/people/40/',
      'http://swapi.dev/api/people/43/',
      'http://swapi.dev/api/people/46/',
      'http://swapi.dev/api/people/51/',
      'http://swapi.dev/api/people/52/',
      'http://swapi.dev/api/people/53/',
      'http://swapi.dev/api/people/58/',
      'http://swapi.dev/api/people/59/',
      'http://swapi.dev/api/people/60/',
      'http://swapi.dev/api/people/61/',
      'http://swapi.dev/api/people/62/',
      'http://swapi.dev/api/people/63/',
      'http://swapi.dev/api/people/64/',
      'http://swapi.dev/api/people/65/',
      'http://swapi.dev/api/people/66/',
      'http://swapi.dev/api/people/67/',
      'http://swapi.dev/api/people/68/',
      'http://swapi.dev/api/people/69/',
      'http://swapi.dev/api/people/70/',
      'http://swapi.dev/api/people/71/',
      'http://swapi.dev/api/people/72/',
      'http://swapi.dev/api/people/73/',
      'http://swapi.dev/api/people/74/',
      'http://swapi.dev/api/people/75/',
      'http://swapi.dev/api/people/76/',
      'http://swapi.dev/api/people/77/',
      'http://swapi.dev/api/people/78/',
      'http://swapi.dev/api/people/82/'
    ],
    planets: [
      'http://swapi.dev/api/planets/1/',
      'http://swapi.dev/api/planets/8/',
      'http://swapi.dev/api/planets/9/',
      'http://swapi.dev/api/planets/10/',
      'http://swapi.dev/api/planets/11/'
    ],
    starships: [
      'http://swapi.dev/api/starships/21/',
      'http://swapi.dev/api/starships/32/',
      'http://swapi.dev/api/starships/39/',
      'http://swapi.dev/api/starships/43/',
      'http://swapi.dev/api/starships/47/',
      'http://swapi.dev/api/starships/48/',
      'http://swapi.dev/api/starships/49/',
      'http://swapi.dev/api/starships/52/',
      'http://swapi.dev/api/starships/58/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/4/',
      'http://swapi.dev/api/vehicles/44/',
      'http://swapi.dev/api/vehicles/45/',
      'http://swapi.dev/api/vehicles/46/',
      'http://swapi.dev/api/vehicles/50/',
      'http://swapi.dev/api/vehicles/51/',
      'http://swapi.dev/api/vehicles/53/',
      'http://swapi.dev/api/vehicles/54/',
      'http://swapi.dev/api/vehicles/55/',
      'http://swapi.dev/api/vehicles/56/',
      'http://swapi.dev/api/vehicles/57/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/6/',
      'http://swapi.dev/api/species/12/',
      'http://swapi.dev/api/species/13/',
      'http://swapi.dev/api/species/15/',
      'http://swapi.dev/api/species/28/',
      'http://swapi.dev/api/species/29/',
      'http://swapi.dev/api/species/30/',
      'http://swapi.dev/api/species/31/',
      'http://swapi.dev/api/species/32/',
      'http://swapi.dev/api/species/33/',
      'http://swapi.dev/api/species/34/',
      'http://swapi.dev/api/species/35/'
    ],
    created: '2014-12-20T10:57:57.886000Z',
    edited: '2014-12-20T20:18:48.516000Z',
    url: 'http://swapi.dev/api/films/5/'
  },
  {
    title: 'Revenge of the Sith',
    episode_id: 3,
    opening_crawl:
      'War! The Republic is crumbling\r\nunder attacks by the ruthless\r\nSith Lord, Count Dooku.\r\nThere are heroes on both sides.\r\nEvil is everywhere.\r\n\r\nIn a stunning move, the\r\nfiendish droid leader, General\r\nGrievous, has swept into the\r\nRepublic capital and kidnapped\r\nChancellor Palpatine, leader of\r\nthe Galactic Senate.\r\n\r\nAs the Separatist Droid Army\r\nattempts to flee the besieged\r\ncapital with their valuable\r\nhostage, two Jedi Knights lead a\r\ndesperate mission to rescue the\r\ncaptive Chancellor....',
    director: 'George Lucas',
    producer: 'Rick McCallum',
    release_date: '2005-05-19',
    characters: [
      'http://swapi.dev/api/people/1/',
      'http://swapi.dev/api/people/2/',
      'http://swapi.dev/api/people/3/',
      'http://swapi.dev/api/people/4/',
      'http://swapi.dev/api/people/5/',
      'http://swapi.dev/api/people/6/',
      'http://swapi.dev/api/people/7/',
      'http://swapi.dev/api/people/10/',
      'http://swapi.dev/api/people/11/',
      'http://swapi.dev/api/people/12/',
      'http://swapi.dev/api/people/13/',
      'http://swapi.dev/api/people/20/',
      'http://swapi.dev/api/people/21/',
      'http://swapi.dev/api/people/33/',
      'http://swapi.dev/api/people/35/',
      'http://swapi.dev/api/people/46/',
      'http://swapi.dev/api/people/51/',
      'http://swapi.dev/api/people/52/',
      'http://swapi.dev/api/people/53/',
      'http://swapi.dev/api/people/54/',
      'http://swapi.dev/api/people/55/',
      'http://swapi.dev/api/people/56/',
      'http://swapi.dev/api/people/58/',
      'http://swapi.dev/api/people/63/',
      'http://swapi.dev/api/people/64/',
      'http://swapi.dev/api/people/67/',
      'http://swapi.dev/api/people/68/',
      'http://swapi.dev/api/people/75/',
      'http://swapi.dev/api/people/78/',
      'http://swapi.dev/api/people/79/',
      'http://swapi.dev/api/people/80/',
      'http://swapi.dev/api/people/81/',
      'http://swapi.dev/api/people/82/',
      'http://swapi.dev/api/people/83/'
    ],
    planets: [
      'http://swapi.dev/api/planets/1/',
      'http://swapi.dev/api/planets/2/',
      'http://swapi.dev/api/planets/5/',
      'http://swapi.dev/api/planets/8/',
      'http://swapi.dev/api/planets/9/',
      'http://swapi.dev/api/planets/12/',
      'http://swapi.dev/api/planets/13/',
      'http://swapi.dev/api/planets/14/',
      'http://swapi.dev/api/planets/15/',
      'http://swapi.dev/api/planets/16/',
      'http://swapi.dev/api/planets/17/',
      'http://swapi.dev/api/planets/18/',
      'http://swapi.dev/api/planets/19/'
    ],
    starships: [
      'http://swapi.dev/api/starships/2/',
      'http://swapi.dev/api/starships/32/',
      'http://swapi.dev/api/starships/48/',
      'http://swapi.dev/api/starships/59/',
      'http://swapi.dev/api/starships/61/',
      'http://swapi.dev/api/starships/63/',
      'http://swapi.dev/api/starships/64/',
      'http://swapi.dev/api/starships/65/',
      'http://swapi.dev/api/starships/66/',
      'http://swapi.dev/api/starships/68/',
      'http://swapi.dev/api/starships/74/',
      'http://swapi.dev/api/starships/75/'
    ],
    vehicles: [
      'http://swapi.dev/api/vehicles/33/',
      'http://swapi.dev/api/vehicles/50/',
      'http://swapi.dev/api/vehicles/53/',
      'http://swapi.dev/api/vehicles/56/',
      'http://swapi.dev/api/vehicles/60/',
      'http://swapi.dev/api/vehicles/62/',
      'http://swapi.dev/api/vehicles/67/',
      'http://swapi.dev/api/vehicles/69/',
      'http://swapi.dev/api/vehicles/70/',
      'http://swapi.dev/api/vehicles/71/',
      'http://swapi.dev/api/vehicles/72/',
      'http://swapi.dev/api/vehicles/73/',
      'http://swapi.dev/api/vehicles/76/'
    ],
    species: [
      'http://swapi.dev/api/species/1/',
      'http://swapi.dev/api/species/2/',
      'http://swapi.dev/api/species/3/',
      'http://swapi.dev/api/species/6/',
      'http://swapi.dev/api/species/15/',
      'http://swapi.dev/api/species/19/',
      'http://swapi.dev/api/species/20/',
      'http://swapi.dev/api/species/23/',
      'http://swapi.dev/api/species/24/',
      'http://swapi.dev/api/species/25/',
      'http://swapi.dev/api/species/26/',
      'http://swapi.dev/api/species/27/',
      'http://swapi.dev/api/species/28/',
      'http://swapi.dev/api/species/29/',
      'http://swapi.dev/api/species/30/',
      'http://swapi.dev/api/species/33/',
      'http://swapi.dev/api/species/34/',
      'http://swapi.dev/api/species/35/',
      'http://swapi.dev/api/species/36/',
      'http://swapi.dev/api/species/37/'
    ],
    created: '2014-12-20T18:49:38.403000Z',
    edited: '2014-12-20T20:47:52.073000Z',
    url: 'http://swapi.dev/api/films/6/'
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

Tip

Set-up the basic navigation first. Then add the movie data.

Last, add the SafeAreaContext to the App component and the SafeAreaView to the screen components.

Solution

rlmckenney/mad9135-stack-navigation-demo (opens new window)

# Resources

Last Updated: : 11/19/2021, 10:40:14 AM