11.1 Layout & Navigation
In this module we will look focus on routing & navigation, 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 and Expo provides an optimized installer ...
expo install react-native-safe-area-context
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 ...
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>
)
}
# Routing & Navigation
React Navigation 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).
# 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
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
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.
yarn add @react-navigation/stack
# 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
Then add the React Navigation modules as per the instructions above.
# Create three simple page components
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>
)
}
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>
)
}
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>
)
}
# 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.
import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
function App() {
return (
<NavigationContainer>
</NavigationContainer>
)
}
export default App
# 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 ...
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
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
# 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'}}/>
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'
}}/>
Remember to adjust the status bar text
You can use the React Native StatusBar component's barStyle
prop to adjust the system status text to light-content
or dark-content
to fit your app's colour scheme. e.g.
<StatusBar barStyle="light-content" />
# 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'
}}
>
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
. 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')}>
# Going back
There are several options here.
- The header will automatically add a < Back button if the user is not on the first page of the stack.
- The hardware back button on Android devices is automatically configured to go back one step in the stack.
- You can programmatically pop the last screen off the stack with
navigation.goBack()
in an onPress handler. - 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')}>
# Passing route params
If you need to pass parameters, like on object id, to the 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})}>
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 */})
}
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 FlatList 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 component to make the list items 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/'
}
]
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.