[MUSIC PLAYING]
SPEAKER: Hello and welcome
back for lecture 6.
So in the previous lecture
we covered a few things--
user input and how to use text input.
We covered some simple input
validation to just make sure
that the input that we receive
is the input that we want.
We talked about keyboard
avoiding view, which
is built into React Native, which
allows us to move inputs out
of the way as the keyboard,
the virtual keyboard appears.
We talked about some various
debugging strategies,
how to log errors and warnings.
We talked about Chrome
Developer Tools, and how
to send our JavaScript to be executed
there rather than on the device itself.
We talked about the React Native
Inspector and react-devtools
to other ways of viewing
the UI, and to solve
bugs that have to do with UI things.
And finally, we talked about
installing external libraries with npm.
And there I alluded to the
library that we're going
to start using called React Navigation.
And today we're joined
by Eric and Brent here,
who were co-authors of this
library called React Navigation.
Brent, right here, works at Expo,
and he helped write React Navigation.
And Eric, over here, was on the
React Native team at Facebook,
and also helped write the
React Navigation library.
So I'll turn it over to
them for React Navigation.
BRENT: Great.
Thank you.
All right.
So I think the first question
we need to answer here
is, what is navigation exactly?
So navigation is a pretty broad term.
It covers pretty much any topic related
to moving between screens in your app,
or moving between different
locations in your app.
Web navigation you might
be familiar with already,
which is very oriented around URLs.
You enter something into
the URL bar, and as a result
of that changing you change the screen
that you're on, or potentially just
an entirely different website.
Mobile apps don't really use
URLs so much, at least not
for navigating within the app.
Usually in mobile apps, URLs are used
for something called deep linking.
We won't be talking about
that too much today,
so I've just added a
link here to the slide.
So if you want to learn more about
deep linking, you can follow that.
So the navigation APIs are very
different between iOS and Android.
They could not be really
more different at all.
There's almost no
similarities, honestly.
And so it's quite a challenge
to do what React Native is
trying to do in many regards
in the realm of navigation.
And try and bring these together and
make a kind of platform-agnostic API
for how to use these different
platform-specific patterns
for navigation, while also making
the API for interfacing with that
very similar across platforms.
And so there are several libraries
that attempt to solve this problem.
We're going to talk about
React Navigation today.
So again, just to give you a gut
feeling of what we're talking about,
on the web with the
desktop web browser, this
is typically what you
would consider navigation.
You scroll somewhere, you
click a link, it brings you
to another URL, the page changes.
There is a Back button, a
Refresh button, Forward button,
and an address bar.
On mobile, with a mobile
browser it's very similar.
The main distinction
that you'll see on mobile
is that there is some UI that
you get for free, actually,
with a mobile web browser, where
you can swipe back on your screen
or swipe forward on
your screen, and that
will allow you to navigate
between different pages
that you visited in your history.
The tradeoff here with
having these gestures
is that you actually have
very little control over them.
So they're there whether
you want to use the gesture
for something else on your page or not.
You're just kind of stuck with them.
And the same thing is
true for the navigation
bar on the bottom of the screen with the
Back button and various other options.
That does interfere with putting
content near the bottom of the screen.
So when it is hidden and
you attempt to tap something
on the bottom of the
screen, it shows up.
And you have to tap again.
So you get a lot, but
there are some costs to it.
Mobile navigation feels more like
this, where maybe you have a Tab
bar on the bottom like this one.
You move between various screens.
When you tap on some link to go
to another screen within the app,
it might slide in over top, and
you can swipe back from there.
And really the key thing here
is that you kind of control
the entire experience
as an app developer.
It's almost like you have your own
sort of browser implementation,
but the only content that you're
browsing is the content of your app.
And the actual behavior that you
get out of navigation in your app
is entirely up to you.
So React Navigation is distinguished
from some other libraries in the React
Native ecosystem in terms of how it
approaches implementing navigation.
So there's two distinct approaches.
The first one is to mainly implement
the logic and the views in JavaScript.
And so the majority
of your implementation
is just plain React all
the way down in the stack.
A second alternative
approach is to write
a wrapper for the existing native
APIs that exist on iOS and Android,
and try to smooth those
differences out using
just basically an alternative
front-end API for how
you interact with these APIs.
React Navigation takes
the first approach.
I won't go into too many details here.
There are some things that are
self-evident from just looking
at the characterizing feature of
the approach in that, if it's mainly
in JavaScript and you are
a JavaScript developer,
you will know how to work
with any part of the tool.
Whereas if you wrap a
native API, you suddenly,
when you want to extend it or
change something or debug a problem,
you have to become familiar with
Swift or Objective-C or Java Kotlin
or something like that.
So we chose the first approach here.
And there's more information
in the docs which
I've linked to here, as well as some
information on alternative libraries
if this isn't your preferred approach.
So first thing we're going to do
here is install React Navigation.
So as you saw last lecture, npm
install, library name, dash dash
save, depending on the version
of npm that you're using.
Newer versions that's not necessary.
One thing that's a
little bit different here
is that we've specified a
version number explicitly.
Typically, if you install with
just the React Navigation package,
it will get the latest stable
version of the package.
However, for the sake
of this lecture, we
are just about to release a new
version of React Navigation.
Currently the stable
version is 1.5 or so.
And React Navigation 2 has
some significant differences.
So we wanted to make sure that the
things that you're learning today
don't go out of date next week.
So if you're referring to this
in the future, keep in mind
you should use a 2.x series of releases.
So some key concepts before we
really get into the code here.
I think it's worth clarifying these
three big terms in React Navigation.
You're going to see these a lot.
The first one is
navigator, the second one
is routes, and then screen components.
So a navigator is a component that
implements a navigation pattern.
So an example would be in the
mobile app that we saw in that video
just moments ago, the tabs are
a certain navigation pattern,
and you would have a navigator that
is associated with that pattern.
We'll see in more detail, of
course, what that means shortly.
Another type is a stack navigator.
So when you tap on something and it
pushes a new screen onto the stack,
and so on and so on as
you add more screens.
And it gives you the
swipe-back behavior.
So each navigator has
one or more routes.
A navigator is a parent of a route,
and a route is a child of a navigator.
Don't worry too much
about this right now.
It will become more clear very shortly.
I just want to make sure we're clear
up front on exactly what these are.
So each route must have a
name and a screen component.
So the name is usually
unique across the app.
That's a safe assumption to make, at
least for now and the near future.
When you get in some more complicated
use cases it may not be true.
But you will hopefully have
the intuition at that point
to understand why that is the case.
The screen component is
a React component that
is rendered when the route is active.
So in the tab, for
example, that we saw, there
is a screen associated
with the Feed tab,
and there is a screen associated with
the Settings tab, and Search tab,
and so on.
And so those, in React
Navigation, are React components.
Now another thing that
Eric will speak about a bit
later is that a screen component
can also be another navigator.
And this is a powerful
concept that would be
very difficult to build apps without.
And so we will discuss that once we
have a bit more foundational knowledge.
So we're going to start off with the
easiest, most simple navigator, and one
that translates directly
from the example that
was being worked on last class,
the Contacts List example.
So the Switch Navigator
is a navigator that
is capable of displaying
one screen at a time.
When a screen goes
inactive, it is unmounted,
and the only action the user can take
is to say I want to go from this screen
to this other screen.
So it's very straightforward.
It kind of looks like this.
You have screen one, and we have a
button, let's say, go to screen two.
If I press Go to Screen
Two, it simply does this.
The other one's gone.
The second one appears.
Basically, as you tap
on these buttons, you're
just switching between the screens.
All right.
And so to create this navigator,
we import createSwitchNavigator
from react-navigation.
We call it with a map where the
keys are the names of the routes,
and the values are
the screen components.
When we actually want
to render it, we just
take the return value of the
createSwitchNavigator function,
and we render it inside
of our app component.
Usually this is at the root of our app.
And we'll see why that is, again,
when we talk about composition.
So this is kind of a new
concept here, the idea
of createSwitchNavigator as being a
function that returns a component.
So I just wanted to take a moment
to explain what that is exactly.
So a createSwitchNavigator
is a higher order component,
in that it is a function that
returns a React component.
So a higher order component, as
defined in the React documentation,
is an advanced technique
for reusing component logic.
And so the component logic
we're reusing in this case
is the behavior of how a
Switch Navigator works.
And we're saying, we want you to
be a Switch Navigator that has
these screens and these route names.
And the logic for how it
operates given those parameters
is built into the
underlying Switch Navigator.
This is pretty similar to the
idea of higher order functions,
if you've ever used those before.
So if you've used something
like forEach or mapFilter,
those sorts of functions, which
are functions that take functions.
Also functions that return functions,
those are higher order functions.
And the same thing applies
for higher order components.
So when we want to go from
one screen to another screen,
we simply call
this.props.navigation.navigate,
and we pass in the route name.
So going back here to the definition,
you can see the route name corresponds
to the screen component.
And when we call Navigate,
we give the route name,
and it simply switches to show the
component corresponding to that route
name.
The navigation prop is passed into
every screen component automatically.
So it's available on
this.props.navigation.
And it has a variety of useful
methods available on it.
We're looking at navigate here.
We'll see a little bit more later about
goBack and setParams and getParam.
And we won't cover some of
these other more advanced ones.
But again, it's worth looking in
the documentation for when you want
to learn some more advanced use cases.
All right.
So let's put this to use.
We're going to start our first example.
So the first thing I'm going to do,
is I'm going to just open up a new tab
while I run exp start dash dash ios.
So exp is the command line equivalent
of xd, which you've been using so far.
I'll make that a little
bit bigger for you.
Hopefully that works.
So it's essentially the same thing.
And running exp start ios is
just like opening a project in xd
and hitting Open on Device with iOS.
I'm just going to open that here.
While that's going on, I'm going
to open up Visual Studio Code.
And we're right inside of our app.
Let's wait for this to start.
OK.
So we have our app up there.
So this is essentially the app
that you finished last class.
And we're going to continue
on this shortly, but first
let's just build this abstract
example of using a Switch Navigator.
And then we'll see how we can integrate
that into what we've already built.
So to do that, I'm actually going
to go back here and make an examples
directory.
And I'm just going to create
a file called examples.
Let's just call it Switch.
0 dash Switch.
And go back in here.
All right.
First thing we're going to do
is import React from React.
Let's make that a bit
bigger for you, as well.
And as we saw before,
createSwitchNavigator
from react-navigation.
OK.
And do class.
OK.
So we know we need to
return something here.
We created our app navigator like
this, calling SwitchNavigator
and passing in a map of route
names and screen components.
So first route name, we'll just go with
the example we've been using so far,
and just call it RouteNameOne.
We could call it CS 50, you
could call it whatever you want.
But for the sake of demonstration,
we'll just call it that.
And now we've run into a situation
where we need a screen component.
So let's create one here.
It's just any old React
component will do.
I will call it ScreenComponentOne.
Let's import a couple of
things from React Native.
Let's do a button and a view.
Just to give some
contents to the screen,
so we can actually do something with it.
And render a view.
Let's make it take up the full screen.
Align everything in the
middle, justify to the middle.
And let's give it a
border, just so we can
see easily the differences
between screen one and screen two.
I'm going to say border width
is 25, and border color--
I'll just make it teal here.
Let's add a button.
And we'll do something
with that in a moment.
And I'll just format that.
It appears we have an error somewhere.
Ah, perfect.
OK.
So this is some invalid
syntax, because we
need to drop in the actual
name of the screen component.
So now what we have here is an app
navigator which has a single route,
and the route renders the
ScreenComponentOne component, which
is simply a button that
does absolutely nothing,
but it's centered in the
middle of the screen.
Now, to actually have
this display in our app,
we need to render the
navigator somewhere.
And going back here, we're just going
to comment all that out for now.
And import example from
examples 0 dash switch.
And render that there.
So if I go back here--
oh, looks like we have a typo.
Ah, of course.
We missed out on a very important step.
We missed out on actually
installing React Navigation,
as I mentioned earlier on.
So to do this, in the slides
I said you can use npm.
There's an alternative
to npm called Yarn.
I personally prefer it.
It's really up to personal
preference here ultimately.
It's fast and it has, in my opinion,
some nicer tooling associated with it.
So I'm going to run Yarn add here.
And yarn add react-navigation
at 2.0.0-beta.3.
And once that's done, as you
can see, it's quite fast.
We can refresh this.
And so we have something here.
We have essentially a
pretty useless thing.
But it is being rendered
by the Switch Navigator.
Now, to demonstrate actually
some useful behavior here,
let's just copy and paste
this screen component
and create ScreenComponentTwo.
I'm going to give it a
different border color.
And I'm going to make it
say, "Go to screen one."
Lastly, I'm going to add
an onPress function here,
so that when you press
on the button, we're
going to navigate to the second
screen from the first screen.
And then I'll add the same
thing to the second screen,
so that when we press on it,
we go back to the first screen.
So you might might remember
from the previous slide,
we do navigation.navigate.
And we currently haven't
defined a route for this,
but we'll just call it RouteNameTwo.
And this similar thing
can be done down here.
Except as per the title,
"Go to screen one,"
we're going to send it to RouteNameOne.
Now I can just change these.
And you can see, when we
press on these buttons,
we are switching from
one screen to the other.
So this is the most simplistic
navigator possible, essentially.
Only show one screen at a time, and we
can switch between the various screens
that we have in the Navigator.
This might look kind of familiar
to you, because this is essentially
what is happening in the
Contact List example.
When you press Add Contact, we're
setting some state on the app component
to say, we are now showing the form.
So we toggle showForm
from false to true.
And we stop rendering
the list of contacts,
and we start rendering the Contact Form.
And this is the same sort of pattern,
but in a more structured sort
of approach.
That hopefully as we
continue, you'll start
to see the benefits of what may seem
like a little bit more complexity
up front.
But let's go ahead and convert
the example that we have--
let's see where we are here.
Yeah, let's convert the example
to use a Switch Navigator.
Right?
So we have that right now.
We're going to keep it
to look exactly the same,
but the only difference is
the underlying implementation,
we use a Switch Navigator.
So let's go back here.
We don't need this anymore.
I'm going to uncomment the whole app.
And current implementation, right.
setState.
And we want to toggle
contacts in that showForm.
So that's state showForm true.
So we're not going to need that anymore.
But there are a few things we need
to do first to get prepared for this.
I'm going to pull out these
components, that are implicitly
sort of screens inside of the app,
into separate components that I'm just
going to add a suffix of screen to.
And that's just the
convention that is very common
when structuring these applications.
So I'm going to make
a screens directory,
and then I'm going to create a--
let's see.
Yeah.
AddContactScreen, and-- that actually
has to be in the screens directory.
And I'm going to create
a Contact List screen.
Screens, Contact.
So this is just a matter of
shuffling stuff around now.
We no longer need showForm.
We'll leave showContacts there for
now, but it's days are numbered.
And we're going to rip this out.
So AddContactForm.
I'll start with this one.
Go into screens, AddContactScreen,
and AddContactForm.
Put that one in here, as well.
And in fact, why don't I just copy
this from an already completed version
of that.
There we go.
So, all I did there was
import the AddContactForm,
and then move some behavior here, which
we'll explain this line in a moment.
So I'll comment that out.
But essentially just render the form
and pass some sort of submit function
through.
I'm going to do the same thing
now with the list screen.
I'm going to go over
here, just copy that in.
So ContactListScreen is
essentially just all of the logic
that we had inside of the app
component previously of toggleContacts.
Some state about whether
we're showing the contacts.
We have a SectionListContacts
component that is rendered down here.
We just don't maintain the
showForm state anymore.
Instead, when you press showForm,
we navigate to the AddContact route.
So let's go back to the app.
We have a good amount of
stuff we can delete here.
This all now lives outside
of the app component.
It's inside of the ContactListScreen.
So we can remove that.
And we can remove various other
things. toggleContacts is now
in the other component.
sort is unused.
showForm is not used here.
Instead, we need to
render something here.
Rather, return something here.
And that needs to be
our Switch Navigator.
So let's add a createSwitchNavigator
from react-navigation.
And it was-- let's
check the name of that.
It was AddContact, was
the name of our route.
And it was AddContactScreen.
And then there was--
what was that referred to as here?
ContactList will be ContactListScreen.
And we want the app to start off as
being on the Contact List screen,
and not on the Add Contact screen.
So I'm just going to have this other
parameter here, initialRouteName,
and say ContactList.
Now, if we, just like that, scroll
right down, and render AppNavigator.
We have a missing import.
Of course, we need to
import AddContactScreen
from screens, AddContactScreen.
And we need to import ContactListScreen
from ContactListScreen.
OK.
That's good.
So let's pop right in here.
Screen, props-- I'm just going to
render an empty view here for now,
so we at least have
something showing up.
And the problem here is that
currently, the way that it worked
is, when it all lived
inside one component,
it was very clear where
our contacts state lived.
It was simply a state inside of the
app, which we passed in as a prop
to our Contact List, and that we updated
by calling addContact on the app, which
then updated the state.
It's a little bit different
when we have something
like this, where we're returning
an AppNavigator component, which
in turn then renders
our Contact List screen.
So we need some way to
say, pass this prop through
to the screens inside
of the application.
And for that, there's
something called screen props.
So, if you specify screen props,
you're able to pass in an object
where that object is passed into every
screen component in the navigator.
So it's a little caveat there.
It's very good for prototyping,
and for examples like this.
However, as you will learn in
the performance lecture later on,
there are better ways to do this.
And you'll talk a little
bit about Redux later on.
And so this is just generally
a potentially useful escape
hatch that you can use
in prototypes and such.
But I wouldn't count on
it in a large application.
It's perfectly fine here, though.
So the way this works is that
we pass in some screen props
to the top level navigator.
And then inside of
our screen components,
we say this.props.screenProps
dot whatever
the thing is that we want to access.
So here what we want to access is,
we want contacts, which is here.
All right.
So let's go back to Contact List.
So as you can see, we're passing in
the SectionListContacts based off
of this.props.screenProps.contacts.
So unless there's a
typo that should work.
And there we go.
And we can navigate to this screen.
However, we currently don't have any
way of actually updating the contact.
Because previously, we were able to call
directly into addContact from the form,
but we're not passing in this prop
anymore to the addContact form.
And so we need to use screenProps
again to pass this function through.
So we can say, addContact
is this.addContact.
And let's format that.
And on AddContactScreen, if
I just uncomment that line,
now that should do what we need.
So, let's say, Eric V., 1, 2, 3, 4, 5.
And I hit Submit.
All right.
So that now updates here.
So certainly there are
some costs here, in terms
of a little bit of added complexity.
But we have added some
structure that now at least
we can continue to grow
in our application.
We were quite limited in what we were
able to do in the Contact List before,
when it all lived inside
of this one component.
Now we have a clear way to add on new
screens and jump between those screens
without having to depend on adding
some new state every time we
want to add another screen.
All right.
Let's move on then to the next topic.
Next topic is Stack Navigator.
So the Switch Navigator is very
primitive in what it can accomplish,
switch from one screen to another.
But typically potentially the most
common navigation in mobile apps,
depending on the app, is
to tap on some button,
and then have it push
some screen on top.
Or, on Android, it kind of
fades in from the bottom.
And then there's some Back
button available to you,
where you press it in the header and
it goes back to the other screen.
And that kind of flow
is extremely common.
And of course, we have
to provide a solution
for that with React Navigation.
And the way that that works is with
something called Stack Navigator.
So it provides the platform-specific
layout animations and gestures
that you'd expect from this
kind of navigation pattern.
So we get the screen sliding
in from right to left.
You can dismiss by swiping.
There are modals that
go from bottom to top,
and you can swipe down,
and that sort of thing.
You can push items from the
stack, you can pop from the stack,
replace the current item, et cetera.
And so it's called Stack, of
course, because of its relationship
to the stack data structure.
So if you are curious about conceptually
how this data manipulation works,
and you're not familiar with
the stack data structure yet,
that's just worth checking out so you
get some good mental model for it.
So the Stack Navigator
looks something like this.
You press Go to Two, in this case.
The two-screen slides on.
You say Go to Three,
third screen slides on.
If you press Back, it goes back.
Swipes, or rather animates, away.
And similar for that one.
So let's push these back on.
And let's see what it looks like
actually behind the scenes right now.
Because we knew that,
with the Switch Navigator,
when we switch from
one screen to another,
we unmount the screen that
we switched away from.
It is now no longer rendered.
It is not in memory.
It does not exist as far as
our application is concerned.
But in a Stack Navigator, we keep
all of these previous routes,
and previous screens,
mounted and in memory.
Because we need to have them there.
We need to know when we're
three screens deep into the app,
we still need to maintain
the scroll position
that we had, for example, in
the feed on the first screen.
And we need to be able to
show the screen immediately
when we start swiping back from
one screen to the other screen.
And so these all need to stay there,
and they need to maintain their state.
There can be exceptions
that you can customize,
but this is the generic
expected behavior.
Creating a Stack Navigator
is very similar to Switch.
We simply swap out the
word Switch for Stack.
And we have something working.
To go from one screen to
another, similarly, we
use the Navigate function.
There is a small difference
here in that Stack actually
supports a tracking history.
So when you call goBack, it
will pop the topmost screen
from the stack and transition
back to the screen before it.
So let's look at how to implement
this inside of our example.
We're going to go back to the app,
and once again comment all this out.
And I'm just going to
add another example here.
This one, of course, will be called
Stack touch examples, 1-stack.js.
And it's very similar to
our Switch, so I'm just
going to paste in our
example to start with.
And switch out the
word Switch for Stack.
And let's see what we get.
So now when I press Go to Screen Two,
it transitions to the second screen.
When I swipe back like this,
we get this kind of gesture.
Or if I press that button, it goes back.
Another way to do it is by
just pressing Go to Screen One.
And it just knows that we already have
screen one here in our route stack.
And so in order to get to it, we have to
pop the top screen and transition back.
So another thing that is very
necessary in Stack Navigators
is the ability to customize the UI
that surrounds the Stack Navigator.
For example, as you can see
here, there's this header.
It has a title.
The title changes depending
on the screen that you're on.
You may want to style it in some certain
way to say that the color for the title
is a certain color, the bar
is a certain color, et cetera.
And so to do that, we
have this static property
that we can use on screen components
called Navigation Options.
Every navigator has a
set of navigation options
that screens can use to configure it.
And you can see the full
list for the Stack Navigator
in the documentation linked here.
For now we're just going
to look at a few of them.
We're going to start with Header
Title, and dig into some styling
there, as well.
So let's go up to
ScreenComponentOne, and let's
set a navigationOptions title.
We'll call this one, I think I said
"First screen" on the example before.
Let's give it a header title.
And for ScreenComponentTwo, I'll
just say "Screen the second."
OK.
So now we see the title,
First screen, and as we
go to screen two, Screen the second.
And it's a small device, so it has
gone ahead and truncated and ellipsized
the title for us in that case.
And if you go back, it does that.
Similarly, the Back
button in this case says
Back, and not the title
of the previous screen,
because there's no space
to render the full title.
So it takes care of a lot of
this nuanced behavior for you,
that users really expect from
navigation on iOS and on Android.
Let's style it a bit.
Let's say the tint color here,
we'll just make it match the border.
So if I set the tint color, what
that impacts is the button color.
So if I had a Back button on the
screen, it would become teal.
It also impacts the
title and any other thing
that is sort of an element that's
rendered on top of the header.
We could set a header background
color through headerStyle.
So if I wanted to make this--
well, it's already quite white.
Let's just say it needs to be a
bit more gray for some reason.
Let's do that.
OK.
So that's a bit gray.
It's kind of boring.
We can make it green.
It's not so legible,
but you get the idea.
So let's get rid of that.
All right.
Let's continue on then.
Pop right back in.
Another thing that's really
important with Stack Navigators
is the ability to pass
parameters between routes.
Typically when you render a component
in React, you would pass in some data
through props.
But as we've seen already with rendering
the navigator at the root of the app,
we have to use some
other kind of construct,
because the navigator itself handles
rendering the components for us.
And so, because we don't
have the capacity here
to even say pass in some screen
props to this next screen,
there is this concept of passing
parameters to different routes.
This is very similar, if
you've used the web before,
to the idea of query
parameters on a route.
So you can add a question
mark to the end of a URL,
and say this value is
this, and this is that.
It's the same sort of idea.
And so there are several
approaches for how
you can manage passing parameters in.
The first one is to pass
in a second argument
to the Navigate function,
which is an object where
the key is the name of the param, and
the value is the value of the param.
You can also update the
params for a given route
by calling setParams, and the
same sort of syntax for that.
And when you actually
want to read the param,
you call getParam, and
pass in the name of it.
And optionally, you can
pass in a default value.
So if it isn't provided, you
fall back to some other value.
So we'll take a look at
what this looks like here.
There we go.
And I'm going to just make a third
screen, where the third screen is going
to just take a random
number, and we're going
to show the random number in our
title, and inside of the screen.
So we can demonstrate
how you can use the param
in various places in your app.
So this one, I'm just going to mark
this as TODO, because we haven't quite
seen how to do that yet.
I'll make a different color
here, let's say purple.
And we will just leave this, let's say,
let's just make this one "Go back."
So goBack.
And let's register the route.
So let's say Three.
OK.
So we have ScreenComponentThree.
It has a title Todo, and it
doesn't do too much inside of it.
Now we're going to look
at the ScreenComponentTwo,
and we're going to change it to pass
in, let's say, number is randomNumber.
Of course, there is no
function called randomNumber.
Let's just quickly define that.
That can just be--
so that's a random
number between 1 and 10.
So now we've made it so on--
let's change this one actually.
So the second screen goes to
screen three instead of one.
And we navigate to the third screen,
and we pass in a param called Number.
So when we want to actually
use this param now,
we will add a Text element here, and say
this.props.navigation.getParam, number.
And let's make it stand out a
bit, and give it a big font size.
And lastly, we know we have
to import this component.
Right.
So we have the number 9 there.
If we go back, now we've
unmounted that component,
and so if we go back again, as
well-- oh, it happened to be 9
this time, also.
There we go.
2.
And so we're passing in random numbers
every time we go to that screen.
We can also change this, so we can add
another button that says setParams.
And we'll say we're setting the
number to another random number.
This one we'll say "New number."
And if you go to screen
two and three, you see a 3.
Now we can update that
param while we're here.
This isn't particularly
useful for changing the param
when we're using it just in the
render function of the component.
But it does get very
useful, because it's
a very important way
for how you can pass
data between the header
of your component
and the actual screen component itself.
So there's an alternative way to
define navigation options, which
is as a function.
And the function takes in some
object with various properties.
The one that's the most important
is the navigation object.
So this is the same as
the navigation object
that is available inside
of the component itself,
when we say this.props.navigation.
And so we know that, since we have
that, we can say navigation getParam,
and get the parameter that's passed
in, and use it inside of our title.
So I'm going to change this.
So the function has to
return an object still.
Before it was an object, now it's
a function that returns an object.
And React Navigation just knows.
It says, if this is a function, let's
call it and pass these values into it,
and then take the return
value, and that will be
the navigation options for this route.
So I'm just going to say number
is navigation.getParam number.
And go to screen three.
So you can see that now the
number is in the header.
You can imagine this is
useful in many cases.
For example, you navigate
to a profile screen,
and you might want to have the name
of the user whose profile you're
visiting up in the header.
There are really numerous use cases
for why you might want to apply this.
All right.
So I think we're in a pretty
good spot there with params.
Why don't we go ahead and add a
button to the header, as well.
So to do this, we can look back here.
See that there's these two
navigation options called
headerLeft and headerRight.
So let's go up there.
And I don't know.
We can add it to screen two.
Let's add-- so we have a title.
Then let's say headerRight,
let's just give it a button.
So on the second screen
now, we have a button
on the top right that says Press Me.
And when we press it,
it just says "pressed."
But we also have access
the navigation object.
So if we want to, we could make this
say navigation.navigate RouteNameThree.
And let's pass in a
not so random number.
Let's pass in 11, which is
impossible to get otherwise.
Right?
And now we have 11 there.
And so you can use this
to essentially do anything
you can do inside of
your Render function.
It's just that the header
is a separate component
from the contents that are rendered
inside of the actual screen itself.
And so to be able to
manipulate those contents,
you need to use the navigation options
to specify what the behavior should be.
And also to add components to the
various positions in the header,
such as the right or left,
which I didn't include here.
By default it's the Back button.
And header title we've
specified as a string,
but that can also be a component.
If we wanted to use an image
component as the title,
we could just swap out the
string there for an image.
We could swap it out
for a button, as well.
It doesn't render so pretty there.
It's not measuring it properly,
but it's working out well, right?
You can render it in that case.
So you have to be a little bit careful
in those situations, but there you go.
Great.
Let's see where we are now.
All right.
Let's take a few minute break,
and we'll continue after the break
with integrating the Stack Navigator
into the Contact List example.
And then with some other
pretty fun stuff around
tabs, and composing navigators together.
We'll end up with--
hopefully we'll get
to the point where we
have a switch with a stack
inside of it, or rather
a switch with a tab inside of it
with stacks inside of the tab.
So some exciting stuff.
Thanks.
ERIC: All right, welcome back.
And thank you, Brent, for introducing
everybody to React Navigation,
covering the Switch
Navigator, and teaching
a little bit about the Stack Navigator.
And now I'd like to go dive into the
code, straight into the examples,
and we're going to take
a look at how we can
put the Stack Navigator to good use.
And hopefully our example app is going
to start to feel a little bit more
like an app as we
continue hacking on it.
So here's where we we're left with.
We've got our App.js, and we've
added a couple of screens.
We've got our App Navigator,
which is a Switch Navigator.
And as you can see, we
can switch to Add Contact,
and it's just instantly
switches over to the form.
But what we'd really
like is we'd like more
of a nice, more traditional transition,
where it pushes in from the side.
So we can use the Stack
Navigator for that.
And the API for the Stack
Navigator, as you've already seen,
is really similar to
the Switch Navigator.
So we can actually start
by just swapping out
the creators for these navigators.
So here where we go into, we're
calling createSwitchNavigator,
it's our higher order component
that sets up our top level
navigator that we're going to render
inside of our app out right here.
But instead of calling that, we're
going to just call createStackNavigator
instead.
So I'm actually just going to
kind of rename it right here.
And let's see what it looks
like inside of our app.
You can see the header appears.
And when we tap Add
Contact, it pushes a screen.
And it pushes this form
screen that we've got.
Now, it still is not
looking super great.
We're going to want to have
some things in the header here,
and we're also going to want to add--
the Add Contact button should
actually be in the header,
because that feels a little bit nicer.
So first, let's go ahead and
jump into our Contact List
screen and our Add Contact
screen, and set up the header.
So our Contact List
screen right here, it
doesn't have any navigation
options set on it.
But we can go ahead and set up
some static navigation options.
And we're going to go ahead and
just put on a normal header, which
is via headerTitle of Contacts.
And we're going to want to do the
same thing in our Add Contact screen.
We're going to want to have roughly
the same sort of navigation options
with Add Contact.
Let's take a look.
Here it says Contacts.
Nice-- Add Contact.
And the Back button is just
working out of the box.
All right.
Now let's move this Add Contact
button up into the header.
So that would be in the
Contact List screen,
because this is where
we're going to want it.
So first, of course, we
just put a headerRight.
And this is one of these
special navigation options
that you can put inside of a stack.
And you can see this link for
more details about what else
you can have there.
But our headerRight, in
this case, let's just
put a button, which we're going to
want to import from React Native.
Or we already are, actually.
So Add.
And let's just have an empty
onPress handler right now.
There we go.
So it doesn't do anything.
And remember, we're going to
want to call navigation.navigate
to the AddContact route.
It's the route name that we have
defined here in the Stack Navigator.
Now, over here, we don't have
access to the navigation prop.
And that's because this
is a static property
that we're putting on our component.
So we can upgrade that by turning this
into a dynamic navigation options,
which is to say that it's a function.
And that function is given
an object of things, right?
And we can access
things.navigation, which
is what we're doing here
by destructuring it.
And what we can do is, we can
put parentheses around here
to signify that this is a
function that's returning
this object of navigation options.
So now hopefully, our button should
have access to navigation.navigate,
and indeed it does.
We can now navigate to our form.
Let's go and delete some of these
old buttons that we don't really
need from our Contact List screen.
OK.
Nice.
So now let's make it so that
when you click on a contact,
you can actually go into a
new Contact Details screen.
That would be really nice.
I'm going to review
that in just a second.
So let's go and add a
brand new screen here
in our Stack Navigator
called ContactDetails.
And we're going to want
to import this screen.
We haven't made it yet, but we'll
import it from the screens place,
from the screens folder.
OK.
So the ContactDetailsScreen,
I'm just going
to jump over here and create
that new screen right here.
And I'm going to want to do
a little bit of copy/paste
just so that we can kind of get up
and running a little faster here.
But this is nothing that
you haven't seen before.
All it's going to be is a empty screen.
OK.
Let's take a look.
Well, we actually aren't linking
to our Contact Details screen,
even though we've registered
the route in the Navigator.
So let's go ahead and do that.
And to do that, you can see
here is the Row component
is where we're actually
rendering the contact row.
But here we don't have access
to this.props.navigation.
But we do have it up here in the
ContactListScreen, where we're
rendering the SectionListContacts.
So here we're providing
all of the contacts
that we are getting in
through our screen props.
And what we can do here is
we can add a new handler
for when a contact gets pressed.
So let's say, onSelectContact,
we're going to want to do something.
And probably going to want to do
something with this.props.navigation.
But first we need to implement
this onSelectContact prop inside
of SectionListContacts.
So I'm just going to open that on up.
The Section List is using
renderItem to render each row.
And this row renderer
here is being declared
outside of our functional
component, SectionListContacts.
So we're going to want to
access the props that are
being passed into SectionListContacts.
So in this case what we can do is, we're
actually going to take this renderItem,
and we're going to bring
it inside of our component.
So this way we can define
it based on the props.
So what we're going to
want to do is, we're
going to want to pass our new prop--
waht was it called--
onSelectContact to the row.
So props.onSelectContact.
OK.
So we're rendering the
row with the contact item.
We've provided the handler.
Now the row itself isn't
currently touchable.
This isn't a button or anything.
And we can make it
touchable by replacing
this view with a touchable component.
So I'm just going to
use Toucable Opacity.
It's kind of the easiest to use.
And this basically means that
you can press this thing,
even though it's still basically a view.
So when the press happens,
what we're going to want to do
is, we're going to want to call
this.props.onSelectContact.
But we need to specify which
contact is being rendered,
or which is being selected and pressed.
And we have that coming
in through props.
We have a lot of information
coming in through props
about our current contact.
So let's just pass that in over here,
and we'll see how we can use that.
OK.
So finally here, we expect that we're
going to have a contact coming in
through here.
And now we have the opportunity to
access this.props.navigation.navigate,
so we can navigate to our
Contact Details screen.
I'm just going to copy over the
call to navigate from there.
Contact Details.
Let's see what happens.
We can tap it.
Oops.
We haven't defined the
prop all the way down.
And I think that's
probably inside of Row.
And so we're referring to this.props,
and there is no this.props.
Because it's a stateless
functional component,
props is just coming in
through the function.
OK.
Now we're not getting
any behavior at all.
And that's because we haven't
actually really gotten to this point.
Let's throw in a debugger right here.
This is a quick trick that
you can use to figure out
where you arrive in your code.
When we tap our contact, we're
not reaching our debugger.
Otherwise, I expect we would
have gotten here in Chrome.
And Chrome has jumped over here.
So what we can do is, we can
put a debugger earlier on.
For example, our SectionListContacts.
We're passing through the
props.onSelectContact.
Here we've got the Touchable Opacity.
We're passing through
props.onSelectContact.
First, I'll put a
debugger statement here
to make sure that we are in
fact reaching our button.
Tap here.
Aha.
OK.
And we can see that props
is in fact our contact.
So let's jump up to the
direct parent of Row.
And I'm just going to wrap a little
shim here, throw the debugger in,
and hopefully we'll be able
to observe, at this point,
whether or not we're reaching here.
So we're still running the old code,
because we were stopped in the Row.
We didn't reach
onSelectContact of our list.
So here, SectionListContacts,
when we're rendering it,
I definitely do expect it to be reaching
the debugger of our Contacts List
screen.
onSelectContact,
SectionListContacts, I'm
going to double check that we're
getting it from the right place here.
OK.
Well this does look
like the right thing.
So I've got my debugger statement here.
And I'm hoping to reach
this top level breakpoint.
OK.
So here we're reaching it.
And now we can see that
we have made it here.
We've got this.props.navigation.
And we're calling dot
navigate with Contact Details.
Let's double check to make sure that
we've registered this correctly.
And I can see now that I
haven't saved my App file.
That seems to have been the issue that
was preventing us from navigating.
So now we tap it, we reach
our breakpoint, I hit Play,
and it's gone and navigated
to our new screen.
So this is a little bit of a live
debugging adventure, when we figure out
how to avoid these things.
Step one is to save your files.
OK.
So we're navigating getting
to our Contact screen.
But unfortunately, the header
is not looking very good,
and we actually aren't even passing
any information about the contact
that we've navigated to.
So the way we can do that
is by passing params.
So when we pass params here,
we can pass an arbitrary object
of various pieces of information,
like contact dot phone number.
And we can also provide the name.
And then inside of our
Contact Details screen,
we can get the param by calling
this.props.navigation.getParam.
And we're going to want to
get the number here, so phone.
Or do I call it number?
Let's call it phone.
OK.
So it's displaying the
number of our contact.
And the other thing is, up in the header
we want to be able to get the param,
as well.
That's the header of
our Contact List screen.
But we can also share
the header of our Details
screen that we haven't
really configured.
So we're going to create a
static navigation options,
and we're going to need
access to the navigation prop.
So this is going to be a
dynamic navigation options,
where we get access to navigation.
And we're going to want to return
an object of options, including
headerRight.
Or, sorry, in this case,
it's just the headerTitle,
which we're going to want to grab
from navigation.getParam name.
So we tap here, and we're
able to see our contact.
Now we also have this button
that says "Go to random contact."
And the idea here is, you might want
to be able to link to other contacts,
maybe to see the contact's
sister or parents.
So in this case, what we can do is we
can implement our goToRandom method.
It should be pretty straightforward.
Now, goToRandom, the first
thing we're going to need to do
is actually get access
to a random contact.
Now, we have our contacts
coming in through
this.props.screenProps.contacts.
So I'm going to go ahead and
grab a little bit of logic
that we're going to use
to find a random contact.
You don't have to look at this too
closely, because it's kind of ugly
code, actually.
So we're just going to grab the contacts
from this.props.screenProps.contacts.
And the phone is going to
be coming from the param
as you can see what we do up here.
I'm just going to copy that right here.
Except here we're accessing navigation.
OK.
So this.props.navigation.getParam
for the phone number.
And then what we can do here is, we're
going to have access to random contact.
I'm just going to put a
debugger statement here,
just so that we can see what
happens when we get to this point.
Hit "Go to random
contact," and hopefully we
get stopped in the debugger.
No contacts.
AUDIENCE: [INAUDIBLE]
ERIC: That's right.
So it's a little bit confusing,
because we're actually stalling in this
While loop right now.
That's why I was saying
this code is kind of bad.
So we have this Contacts file, which
generates our content, in this case,
we're only getting one contact.
So when we try to get another random
one, it's not going so smoothly.
OK.
Now we've got multiple contacts.
And when we tap "Go to random
contact," we get here to our debugger.
And let's take a look at randomContact.
It's probably an object
with name and phone number.
Great.
So let's go ahead and
navigate to another Contact
screen on Contact Details.
So this.props.navigation.navigate
to ContactDetails.
And we're going to want to
pass the same information in.
So we have the name, which
is the randomContact.name.
And we're also going to
have the phone number.
OK.
So let's see what happens here.
We're going to tap on our first contact.
We're going to tap "Go
to random contact."
Oh, that's strange.
I expected to navigate to a new screen.
Well, it turns out
that we don't actually
need to navigate to a new
screen, because we're already
on Contact Details.
So we called navigate to Contact
Details with setting params,
we provided these additional params.
But what we're actually
doing is, we're just
setting the params on
the current route, which
is not exactly what we were going for.
So instead, we can use
this other prop that's
on the navigation prop, called Push.
Now, Push is always going
to push a new screen,
and you can also provide params to Push.
So Navigate is going to
navigate to your current route
as identified by your route name.
All right.
So let's go ahead and change
this Navigate to Push.
OK.
So we tap on one contact.
We see it.
We go to another contact.
And we go to all of our random contacts.
This is great.
Now, the Push is only available
inside of a Stack Navigator.
And there are a few other things that
are specific to a Stack Navigator.
Don't mind me while I
rearrange this screen.
So there's other things like
Push, which adds a new screen.
Pop takes you to the previous
screen inside of the stack.
PopToTop takes you to the
top screen inside the stack.
And Replace is like what we were just
doing by accident with the Navigate
functionality.
Now, let's talk about
composing navigators.
This is a pretty powerful
technique that allows
you to put one whole navigator
visually inside of another.
Now, you'll get a better
intuition for this
as we move forward,
about when you want to be
putting a navigator inside of another.
But generally, if you see
a header on the screen,
but you also see a bar on
the screen at the same time,
then that's a case when
one of these navigators
is actually inside of the other.
And you'll notice that
by switching tabs,
you'll often move away
from the whole header.
Or, it could be composed
the other direction.
Now, the way that we
do this is, we actually
register a navigator as the screen
component of another navigator.
And you should always be careful
to make sure that your app only
has one top-level navigator.
And the really great thing
about composing navigators
is that you can navigate pretty
effortlessly between all of them.
So if you just use the
Navigate functionality,
and you refer to a route name
that's inside of another navigator,
you'll automatically get over there.
And goBack also works
between different navigators,
and that's really essential
for supporting the Android Back
button so that the user
can always get back,
even if they're inside of a
deeper navigator in the app.
Cool.
So this is what it looks
like to compose a navigator.
You can see that, in this case, we're
creating a stack navigator as per usual
with two screen components.
But then down here when we're
creating a Switch Navigator--
it's our top-level
navigator as you can see,
because it's an App Navigator--
we're registering the Stack Navigator
inside of it as the main route.
All right.
So like I said earlier, just one gotcha
you should really be careful about
is to never render a navigator
inside of a screen like this.
You only ever want to render a
navigator by itself at the top level.
And you always want to make sure that
the navigators are linked together
inside the higher order
components like you see here.
Cool.
So let's go ahead and put our
Stack Navigator that we just
made inside of a new navigator.
All right.
So we can create a brand
new navigator here.
Instead of this App Navigator,
let's call it the Main Navigator.
And that's a Stack Navigator.
Now let's create a new App Navigator.
And the reason we're going to create
these navigators inside of each other
is because sometimes, you might not
even want to see the stack at all.
Here we've got a Stack
Navigator, but how about let's
create an example where you
want to log in to the app
before you even see the main stack.
So in that case, you're going
to be switched away from it,
and you're only going
to see a login screen up
until you're ready to
see the actual stack.
So that's why we're using a switch on
the outside of our Stack Navigator.
Let's go ahead and register the first
route, which would be the Main route.
That's just a name.
We can call it whatever
we want, but I'm going
to call it Main, because it's our
Main Navigator once you're logged in.
And I'm also going to
create Login, which
is going to be a login screen
that we haven't created yet.
I'm going to set the initial
route name to be the Login
screen, because we're going to want
you to be logged out at the beginning.
OK.
So I'm going to get the Switch
Navigator from React Navigation.
And I'm going to get
the Screen Navigator
from not yet implemented area.
OK.
So let's go ahead and create our screen.
And I'm going to copy and paste
a super simple Login screen.
And our Login screen is going
to have a couple of styles.
OK.
So let's see, what
does our app look like.
I think I might not
have saved the App file.
OK.
So this is the Login screen.
This warning here is because
we're currently debugging,
and we're kind of done
with that right now.
OK.
So now we've got our Login screen.
We have that, because the
App Navigator that we're
rendering down here inside of the
app, it is just a Switch Navigator.
And the initial route is Login.
So all we see is the Login screen.
When we press to log in,
well, we haven't actually
implemented the Login functionality.
So let's pretend that we have a
bunch of Login logic right here.
And instead of actually
doing that, we're
just going to jump straight
to the navigation part.
So let's see this.props.navigation.
And we're going to navigate to the
Main screen when you tap Log in.
OK.
And it switches us over to our stack
that we've already implemented.
Now, what's great about
the Navigate function,
and what's great about
composing navigators,
is that you can actually refer to
several different route names here.
So here, of course, we're referring to
the route name for the other navigator.
So it's just telling us to switch to
this navigator, whatever state that
navigator currently is.
The initial route named for that
navigator is the ContactList,
so that's why we see that.
But we could also explicitly
navigate to the Contact List.
Let's try that.
Press to Log in, you
jump to the Contact List.
OK.
What if you want to explicitly
navigate to something else?
Like let's explicitly
navigate to Add Contact.
Just as an example.
It wouldn't really
make sense in our app.
But maybe Add Contact is the
first thing that you want somebody
to do once they log in.
OK?
And it jumps you deep inside
the stack, but it still
is normal stack navigation.
You still go back inside of the stack.
So here, that's a very simple
example of navigator composition.
So now, we've seen Switch
Navigator, which allows
us to switch between several screens.
But Tab Navigator is a
little bit more special,
because it actually has a tab
bar that's useful for switching
between the different screens.
And also, it'll keep the previous
screens that had been available,
it'll keep their state around.
So it doesn't actually unmount
the components that go away.
And that's handy, because when you
want to switch back to the screen
it's really fast, and
the state is still there.
If you had scrolled down
inside of a certain tab,
and you switched tabs and switched
back, it's still going to be there.
Now, there are several Tab Navigators
that now ship with React Navigation,
including two of these
Material Themes Navigators,
and a simple Tab Navigator, which
is Create Bottom Tab Navigator.
And as per the other navigators,
the Navigate function
and the goBack function still work.
So Navigate is how you
switch to different tabs,
and goBack actually does have
behavior on Tab Navigator.
It takes you back to the first tab.
And this is relevant usually
on the Android Back button,
because you want to be able to jump
somebody back to the first tab.
But you don't want this
in every case exactly.
So the Tab Navigator's goBack
behavior can be configured.
It doesn't necessarily have to
take you back to the first tab.
So with Tab Navigators you can switch
between two tabs, but keep in mind
that the previous tab is still there.
It's just not visible.
All right.
And the way that you create a Tab
Navigator is much like the way
that you create any other navigator.
You're going to register a couple
of routes by their route name,
and you're going to
provide a screen component.
OK.
Maybe we should just go
jump into our application
now and implement some of these tabs.
OK.
So this is where we are right now.
Can press to log in.
OK.
The other thing that I'm going to
do that I missed before, actually
with Stack Navigation, we're
going to go ahead and theme it.
We're just going to give
it a little bit of a color.
We've got these navigation
options that, in this case,
we're configuring the header.
So this is available inside
of a Stack Navigator.
So I'm going to go here to our stack.
In addition to specifying
the initial route name,
I'm going to specify some
navigation options that
are going to identify the tint color.
Ooh.
OK.
This button we had
rendered by hand, which
is why it's not actually lining up.
So let's go ahead and
fix that really quickly.
That would be on the
Contact List screen.
We can just provide a color right here.
OK.
The other thing is, of course, our
Login screen was deep linking here.
Let's just make it go
to the Main Navigator.
OK.
So now let's actually go and jump
into adding our Tab Navigator.
So I'm going to go into our app.
And instead of the Main
Navigator, let's just
go ahead and call this the Contacts Tab.
Because we're going to want to make it
so that this whole stack of navigation
happens inside of a particular tab.
And you'll notice that it's a pretty
common pattern, especially on iOS apps.
So let's call this the Contacts Tab.
And we're going to want to
create a new navigator for the--
what did we call it--
the Main Navigator.
So that can be our tabs.
So the Main Navigator
is createTabNavigator.
And we're going to want to set
up a couple of routes here,
including, of course, the Contacts Tab.
And let's create a new tab.
And that's going to be under Contacts.
Let's create a new tab for a
different area of your application
that really has nothing
to do with the contacts.
I think a pretty simple
example that's somewhat common
is like a Settings Tab,
where you can go and change
some other configuration about the app.
Settings screen.
So Settings screen, we're
going to go import from here.
Which we haven't quite created
it yet, but we're going
to go ahead and do that right now.
And the Settings screen, I'm going to do
a little bit of copy/paste once again.
And all we're going to be doing is
just saying, This is a Settings screen.
It doesn't even need a navigation
link or anything right now,
because the tabs will be visible.
So I haven't saved the app.
Oh.
I need to import createTabNavigator
from React Navigation.
OK.
We're going to press
to log in, switching
to our Main Navigator, which is tabs.
OK.
It seems that in the copied/pasted
content that I had, I had a slight bug.
I'm going to go ahead and
just fix that by changing
the scroll view to a normal view.
It's going to be little simpler.
But now you can see that we have
tabs at the bottom of the screen.
And the first tab that's
selected is the Contacts Tab.
The second tab doesn't even have
a header or anything inside of it.
And that's because we've switched
entirely away from the other navigator,
and the header was provided
by the Stack Navigator.
So these tabs are looking kind of ugly.
Let's go ahead and
theme them a little bit.
So one trick that we
have for theming tabs
is by setting these tab bar options.
We can set the active tint color,
which is the color of the active tab.
So let's jump into there.
Here where we're creating
our Tab Navigator,
we can set Tab Bar Options
and Active Tab Color.
I'm going to copy that
from right here so that we
have a nice cohesive theme for our app.
Press to log in.
Oops.
My guess is I had a nice typo here.
So let me go ahead and find my--
I see.
I said-- it's Active Tint
Color and not Active Tab Color.
OK.
So now our tint color matches.
Now generally, when we have tabs
at the bottom on an iOS app,
you really want to have icons, because
this just looks bizarre if you don't.
So let's introduce a new concept of
adding vector icons to our application.
Now this is how you can
specify the Tab Bar Icon.
But first we're going to need
to install a new library.
So we're going to go to do npm install
dash save, react-native-vector-icons.
In my case, I'm going to use Yarn.
I'm going to go right here and say,
yarn add react-native-vector-icons.
All right.
While that's installing, I'm
going to go start using it.
As you can see, you can
import it like this,
and render it with a couple
of conventions like that.
So I'm going to grab my snippet here.
So here you can see that
we're manually applying
navigation options onto the main stack.
Or rather, instead of the
main stack, in this case
we've called it the Contacts Tab.
So we're going to set the
options for the Contacts Tab.
And here we are using a pretty fun
trick where we've got a string template.
And the Tab Bar Icon is a
pretty special navigation
option that is defined as a function.
And it's told both
what the tint color is,
and whether or not the
tab is currently focused.
And the reason we need to know
whether or not the tab is focused
is because, generally, we're going
to render a different style of icon.
So if it's focused, we're going
to just render iOS Contacts.
And if it's not focused, then we're
going to render iOS Contacts Outline.
So that's what this trick
is doing inside of this--
you know, we've got a ternary
inside of our string template.
So let's see if that works.
I need to import Ionicons from
react-native-vector-icons.
OK.
I'm going to press to log in,
and our icon is showing up here.
You can see that when we blur it,
it switches to a different icon.
So that's why we have that
kind of crazy template string
that we're using to
select the current icon.
So let's go ahead and do something
similar for the Settings screen.
But here we're going to actually put
it on the screen static navigation
options.
So here, the static
navigation options are empty.
I'm going to want to
provide a Tab Bar Icon.
And here we're going to provide
just the same one for now,
just to make sure that it works.
OK.
That looks a little weird.
So I think it's going to be iOS options.
Ooh, options.
Looking nice.
Great.
So here, just to do a quick recap
of all the navigation features
that we've added to the app in a
relatively short period of time,
I'm just going to open up the App file.
And we're going to start
at the bottom, where
we're rendering our App Navigator.
Now our App Navigator
can be given access
to screen props, which are
various properties that are going
to be available on every single screen.
Of course, in larger
applications, you might not
want to use screen
props, because it will
it'll cause every screen to re-render
when any of these screen props changes.
So you might want to use a different
technique to deal with that.
But here you can see we're just
rendering our App Navigator.
Our App Navigator is a
higher order function,
is the result of a higher
order function call.
It's a higher order component.
It's that we're creating
a Switch Navigator.
And that's why, at the very beginning,
it covers up the whole screen,
because it's our
top-level navigator that's
switching away from the Tab Navigator.
And that's what we have in here.
Inside of our Main Navigator,
this is a Tab Navigator,
where we've got two tabs.
You've got the Contacts
Tab and the Settings Tab.
So first, we need to navigate on the
outer navigator, which is the switch,
and now we can access
the inner navigators.
In this case, the next inner
navigator is allowing us
to switch between these different tabs.
Of course, inside of the main
tab, inside of the Contacts Tab
we have a whole stack.
So that's what we're setting up
up here with createStackNavigator.
We're registering three
screens inside of our stack.
And inside of each of our screens we're
setting various navigation options.
And the default navigation options are
the ones that are provided down here.
The navigation options are what's
setting up the button in the header
and the title, as well as the color.
And each of these screens
are able to navigate
between each other using the Navigate
functionality in this dot props dot
navigation.
So I think that's a quick
introduction to what it's
like to use React Navigation
inside of a fresh React Native app.
And I hope you enjoyed it.
And if you've got any
questions, feel free to take
a look at some of these
additional resources
that we have available for
you, and get in touch with me
and Brent on Twitter and GitHub.
Thanks.
