[MUSIC PLAYING]
SPEAKER 1: Hello and welcome
for Lecture 3 in React Native.
So previous lecture we talked
about a bunch of different topics;
one being classes and how ES6
allows you to write classes.
React, we talked about
the library by Facebook
that allows you to write
declarative programming.
We talked about what imperative
and declarative programming were
and how React allows you
to write declaratively.
We talked about props, which
are basically an object that
are passed down to elements.
We talked about state, which is a
management system for allowing you
to track state in a class component.
We implemented the to do app in
React and then we teased at something
called React Native.
And so this lecture we'll be
talking a lot about React Native.
React Native is a framework
that relies on React Core.
And so a lot of the paradigms that apply
to React also apply to React Native.
And it allows us to build mobile
apps using only JavaScript.
And so, as the React team like
to say when this was released,
you can learn once and write everywhere.
And so React Native
supports iOS and Android,
and we'll see later today
how we get that going.
And so how exactly does this work?
How are we allowed to write JavaScript
and have it run on mobile devices?
So first, the JavaScript is bundled.
So, just like in React, what happens
are a couple of different steps
where your JavaScript is transpilaged
so going from ES6, ES7, ES-next,
down to ES5 code, and
it's also minified.
And so throughout the process you
go from a bunch of different files
all to one big JavaScript bundle.
This runs on your phone.
There are separate threads
for UI layout and JavaScript.
And so, as we saw, if we're
running JavaScript in the browser
and that locks up, then nothing works.
But in React Native there
are actually separate threads
for the UI layout and JavaScript.
And these different threads communicate
asynchronously through a bridge.
And so the JavaScript
thread will request
UI elements to be shown and
then, like I alluded to earlier,
the JavaScript thread can be
blocked and the UI still works.
And so what do I mean by this bridge?
And so what ends up happening
is there are separate threads.
So there's one thread for the UI and
there's one thread for JavaScript.
And so say we're writing React and
we have something like a button
that we want to be shown.
Basically what happens is
there's this bridge which will
communicate between these two threads.
And so the JavaScript
will basically say,
hey UI thread I want a view or a button.
And then UI will basically
say, OK here it is a button.
And then if I, as a
user, go ahead and press
that the UI will actually
send over to the JavaScript,
oh the button was pressed.
And so this bridge here
is asynchronous, so
if something happens on the JavaScript
and the JavaScript is actually
clogged and blocking, the UI
thread can still do its thing
and I'll show you an
example of that in a second.
And, conversely, when you
touch something on the UI
the JavaScript doesn't know
until the bridge basically says,
hey, this button was pressed and the
UI can talk to the JavaScript that way.
And so let's see some example where
we can lock up that JavaScript thread
and not have the UI lock up.
And so here we are in
the Snack, snack.expo.io,
and this allows us to run React Native
and have it all happen in the browser.
And so a few lectures ago we wrote this
blocking method that basically locks up
the JavaScript thread.
So we can go ahead and do that again.
So say we have a method
called block JavaScript.
And what that does is you can say, we're
going to block and then do this thing,
so while date.now so we can say,
cons done is five seconds from now.
And we can say, while it has not
been that much time just do nothing.
And then when that's done
we can say, OK we're done.
And so down here, let's
actually create a scroll view--
we'll see what that is in a second--
and a button.
And we actually don't care
about any of all that stuff.
And so, when this
button is clicked, we're
going to go ahead and
block that JavaScript.
All right.
So everybody following?
So, so far we have a scroll view
which is basically just a view that
can scroll back and forth.
We have a button that says block
JavaScript, and when it's clicked,
it will run this function
that blocks the JavaScript.
And so watch what happens
when I click this button.
Small bug.
All right here's a chance.
Who can spot the bug?
Oh, on press.
So on press, it will actually
block the JavaScript.
And you see how it still is scrolling,
but that button is locked up.
And then only after five seconds
have passed do the logs come through
and then the button returns
to its normal state.
But notice how when it
was stuck and locked,
when the JavaScript thread
was locked, we still
had the ability to
scroll back and forth.
That's because all of the JavaScript
is controlled on one thread
whereas on the other thread all of the
UI elements still worked as intended.
And so even though the JavaScript
thread was locked up here,
it was in this while loop
doing nothing, the UI elements
were still able to
scroll back and forth.
And so it's not as big
of a deal if you lock up
the JavaScript thread in React
Native but it's still a big deal
because none of your
event handlers will fire.
So any questions about how React Native
works, how these UI and JavaScript
threads run separately in the bridge?
Great.
And so what are some of the differences
between React Native and React Web
which we've been talking about thus far?
So there are differences
in base components.
So as you saw in my quick example,
things like scroll view or capital
button do not exist in web.
Things like style, the way
that you style elements,
is slightly different in React
Native and you don't actually
have browser APIs anymore.
So things like CSS, animations,
canvas, SVG, things like that
don't actually exist in React Native.
But there are actually things
that have been polyfilled.
So polyfilled is a term that people use
to mean some methods or functions that
might exist in one environment do not
necessarily exist in all environments.
And by polyfilling these we can
actually implement them such
that all environments
will actually have these.
And so fetch is something that's
not supported by all browsers,
but by polyfilling it
you can actually include
code that will implement fetch
if it doesn't exist already.
And so things like fetch timers like
set interval or console or console.log,
console.warn, and stuff like
that have been polyfilled so
that they work in React Native as well.
And also the way that
you handle navigation
is slightly different in
React Native, and we'll
talk about that in a future lecture.
And so I said that React Native base
components are slightly different.
And so what do I mean there?
So in React Web we had access to
things like div or span or P image,
and we can just declare those globally.
But in React Native we actually have to
import from the React Native library,
and we'll see how to do
that in a little bit.
And so divs no longer exist and
what we use instead are Views.
So View with a capital V is basically
a cross-platform, just blank E-Y slate.
So basically the same thing as a div.
There's no such thing
as span or P anymore
and so instead we use this text.
And so what's unique in React
Native is that all text actually
must be wrapped by this text tag.
As you saw in this previous
example lower case button
doesn't exist anymore.
Instead, we use capitol Button
with a slightly different API.
And so from React Web, if you
want to attach a handler to that
you do on click.
Whereas, in React Native, you
do on press which was actually
the bug in the code earlier.
And lastly we have these things
called scroll views or lists which
don't really exist in web world, but
they do exist a lot in React Native,
and we'll be talking about
those in the future as well.
Of course there are many,
many other components
and, if you want to explore them,
the documentation is really good.
Cool, so let's actually
take that example
that we wrote last lecture,
the to do app, and actually
translate it into React Native.
And so I have here this implementation,
which is exactly the code
that we wrote in the previous lecture.
And what we're going to do is
copy and paste that into the Snack
that we saw earlier and go ahead and
translate that into React Native.
So this is just the command
to copy it and let's actually
paste that into here.
So of course there's going to be many
errors just because this is React Web
and we're trying to run
this in React Native.
And so let's go ahead and
try to fix those errors.
And so first we see stuff like
LI, input, button, and those
don't exist in React Native.
And so we'll have to first
replace those React Web
components with React Native ones.
And so this rendering
does not exist anymore.
And so let's first do import
some stuff from React Native.
And we'll be talking about imports
and exports a little bit later,
but just bear with me for now.
And so some things that we're
going to need are stuff like View,
we'll need a Button and we'll need text.
And we'll need some scrolling
views and then maybe
some more stuff in a little bit.
So first let's work on
that quick to do component.
And so we have a list item here,
instead let's actually use a View.
Let's actually get rid of this input for
now, and we'll add that in a little bit
later.
But how are we going to change this
lowercase button to React Native?
Well first we need to replace it
with the capital Button, which
is React Natives version of the button.
It no longer has an on click
property and so instead we'll
pass an on press prop and then we don't
actually wrap the content any more
instead we pass a title prop.
And so that button's done.
What are we going to do for span?
Anyone?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: Yeah, we'll
use a text instead.
And now our to do is done.
So now let's start looking
into this app component.
So first let's get rid of this render,
which does not exist in React Native,
and let's start working our way
through this big return function here.
So first we have a div.
Instead of a div let's
go ahead and use a View.
And then we have a to do count.
So what are we going to
use instead of this div?
We can't use a View
otherwise an error will
be thrown because remember the
only way that we can include text
in React Native is by wrapping it in
this text component and same thing
with this.
All right, we see another button
and we've seen a button before,
so all we have to do is replace
that lowercase b with a capital B,
change on click to on press and
change the content to be title.
And then we're done there.
All right, UL, unordered lists.
So how might we handle this
unordered list in React Native?
So lists, ULs and ordered
lists don't actually
exist in React Native, and the
way that we handled those instead
are by using the scrolling
components because we don't know
how long that list is going
to get and so we better
assume it's going to get pretty long
and be able to scroll through them
if we needed.
And so unordered lists we
replace with scroll view
and now we have what
we were looking for.
So all of the React Native components,
the React components sorry,
we've changed to React Native
components and now we have--
Oops, something's breaking still.
Prompt is another one
of those browser APIs
that just does not exist in
the React Native world which
caused our code to crash.
And so rather than using
one of these browser
APIs let's just replace it with
some hard coded text for now,
maybe something like to do, number,
and then whatever it's ID is.
And rather than
incrementing ID down there
let's actually increment it up here.
And so now it works.
So we have to do number
one, to do number two
and you can see how we add those.
And so we'll fix the
style in the future,
but basically does
anybody have questions
on going from React Web to React Native?
What we did there was just replace
all the React Web components
with the React Native components.
And it is almost as easy as command
effing and replacing like that.
Great.
And so how are you going to go
about styling those components?
So in React Web the way
we did that was just
by adding a class name and then
styling in CSS, but in React Native
we don't have this concept of CSS.
So the way that React
Native handles that
is by actually using JavaScript objects
for styling and what that gives us
is the ability to use dynamic styles.
Object keys in these objects
are based on CSS properties,
so we have stuff like margin top,
margin bottom, margin padding.
And the layout system
that we used is Flexbox
and so, if you're familiar
with the Flexbox system in web,
it's almost exactly the
same in React Native.
One of the key differences
is that rather than
defaulting to row we default to
laying out things in columns.
So, in React Web, we have this
concept of pixels or percentages,
but in React Native we actually
use unit-less numbers for length.
Which is good because there
are so many different devices
that this runs on with
different pixel densities
that having a unit-less number allows
us to abstract that pixel density out.
The style prop, so the way that
you style a given component
is by assigning that JavaScript
object to a style prop
and it can actually
take an array of styles.
And so, if you wanted to have a bunch
of different class names in React Web
you'd just start adding those
with a space in between.
But in React Native you handled
that by passing an array of styles.
So let's go ahead and add styles
to this app that we have here.
So first, let's go ahead
and style this view.
And so right now, as you see, each
to do has a Delete button and a
to do right under it, whereas in web
we had the Delete button next to that
to do.
And so let's try to
figure out exactly how we
can get that Delete button over
here and the to do to be next to it.
And so does anybody have any ideas
about how we might want to do that?
We know we're going to
have to pass a style prop,
and we know that it's
going to be an object.
And so this looks weird to
have those double curlies
but the outer curlies
mean, hey here comes
some JavaScript and the inner
curlies are just an object
literal like we've seen before.
And so how might we get
those to dos to be in a row?
So we saw before that React Native uses
Flexbox in order to handle it's layout.
And so we can just say, hey we want
the flex direction, rather than being
column by default, let's set it to row.
And so now we have the Delete
button next to the to do.
But it's annoying me a little bit how
that button is slightly below the text.
And so how might we get those
items to be aligned to center?
Well in Flexbox we have this
thing called align items
and then you just say, hey
align those to be center.
Then all of a sudden we
have it aligned center.
And just confirming that
delete button does indeed work.
Great.
Anybody notice any other
bad style bugs over here?
So look at this.
So most phones will have some
nav bar, and that nav bar
will have stuff like if you're
connected to Wi-Fi, the time and etc.
But that first view is actually
going all the way to the top.
And so how might we get all this
content to be slightly moved down?
So how would we do that in Web?
AUDIENCE: Add a margin.
SPEAKER 1: Yeah we would add a
margin or some padding or something
to move the content from
the top slightly down.
And so we could do that
in React Native as well.
So you can say with this view, let's
actually put a padding on the top
and let's just say something like
50 which is somewhat arbitrary.
And now we've gone ahead and
moved that down slightly.
But what if we wanted to move it down
exactly the same amount as the status
bar?
Well there's this great
tool called Expo which
we'll talk about in length later today.
They're also the people
who designed Snack.
And they actually give you
this thing called constant
so we can do import constants from Expo.
And we can actually say,
hey padding top rather
than assigning an arbitrary value of
50 let's do constants.statusbarheight
and that will actually give you
that exact status bar height
even if you're on different phones.
And so, again, we'll
talk about Expo and we'll
talk about importing and
exporting later today.
But just FYI there's this thing called
constants.statusbarheight which will
give us exactly that status bar height.
And now we have a to do app
that doesn't look half bad.
Cool.
So there's actually this
thing called style sheet
which is part of React Native which has
some optimizations for these styles.
And so we talked about earlier how the
way that your JavaScript communicates
with the UI throughout
is through this bridge.
And so that means every single
time you want a view with the style
you need to send those style
attributes over the bridge.
There's actually a way
that you can optimize this.
And so the Facebook team
created this thing called
style sheet which does this for you.
So it's basically the same thing
as creating objects for style,
but as an additional optimization that
rather than sending this style object
over the bridge we can only send IDs.
And so say we have these objects,
rather than passing the full object
every time you can just
say, hey this object,
let's assign it this
arbitrary ID of one.
And so every time we say, hey
this should have a style of one,
the UI thread will know, oh, I
know exactly what style that means.
And so to do that, all we have to do
is import this thing called style sheet
from React Native and we can do this.
And so we're saying we're declaring our
styles as a constant outside of our app
and we're saying, hey
create this style sheet
and we're going to pass into
you an object where the keys map
with how we're going to use this later.
And so we can go ahead
and abstract this out.
And so we can say, this
here we're actually
going to call our to do container.
And our to do container will just say,
all right flex in the row direction
and align your items to be centered.
And then down here
for style we just say,
oh, we want to use styles.todocontainer.
And let's actually lowercase
this for convention.
And as you can see those
styles still get applied.
And why else might this pattern be good?
Does anybody see something
better about this pattern?
AUDIENCE: It's reusable.
SPEAKER 1: Yeah exactly, it's reusable.
And so say we wanted to
have something else that
had very similar styles
to to do container
we can actually use that again.
And then if we wanted to change
both of them at the same time
we could do it by using
this abstracted out object.
And so let's do the app container
and set that equal to this object.
And then down here for this view
let's do styles.appcontainer.
And so there's actually an
even better reason to do this
and it's because every
single time we rendered,
we used to be building a
new style object to pass.
And now we're just using
that same reference
to that object that we created
outside of this component.
And so that's just an additional
optimization that, using this pattern,
creating the styles outside of
the component allows us to do.
Cool.
Any questions on styles and styling?
Great.
So let's talk about event handling.
So unlike Web not every component
has every single interaction.
And so in Web, if we had a div, we
can assign an onClick to that div
or if we add a list item or a list,
anything we can assign an onClick to.
But unlike Web there are only a few
touchable components in React Native
and those are a button,
which we've used before.
These three things called touchable
opacity, touchable highlight
and touchable without
feedback, which are just
three basic components that have
slightly different reactions when
you touch them.
An then lastly, this thing
called touchable native feedback
which is this native component
that you can only use on Android.
And so in Web, when you
had an event handler,
that handler would receive
that event as an argument.
But that's not necessarily true
for all React Native handlers.
And so in order just to
find out how those work
you basically have to
consult the documentation.
The documentation for React
Native is really good.
I recommend that you
peruse them just to see
what components are available
to you and those component APIs.
And basically most of the
stuff that you want to do
is already pre-built for you.
And so, even though
there's no such thing
as a checkbox component in React Native,
there is actually a way to do that.
And so let's go ahead
and add this thing which
is similar to a checkbox
in that it's a Boolean flag
but it's not really exactly
stylistically the same.
And so let's add this
thing called a switch.
As a switch you'll see what
it looks like in a moment
but it's basically just a Boolean flag
that we're going to use in this example
rather than using a checkbox.
So before what we had here was an
input of type checkbox and instead
we're going to use a switch.
And the value of that is going to be
whether the props.TODO is checked.
And so now when we add
a TODO we see the switch
that can be flipped back and forth.
But if you notice, every
time I try to flip it on it
immediately turns back off.
Can anybody spot why that's happening?
So we have this value set to props.TODO
checked, and down here do we ever
update that value?
No we don't.
So we have this thing called Toggle
TODO which we implemented last week,
which, given some TODOs ID will
flip that Boolean checked flag.
But we never actually hook
that up for this example.
So in the TODO component here
we're passing down an onToggle prop
but we never actually use it up here.
And so here we should actually
have the switch when we do on--
what's it called-- on value change.
And I only know this because
that's what the documentation says.
And so when that value changed,
I should run props.onToggle,
which is the name of the
prop that we're passing down
from this parent component.
And so now when we
click TODO it updates.
And as you see right here the unchecked
TODO count still updates as expected.
And so now if we create a bunch
we can see those numbers changing.
We can see the checking and
toggling works as expected.
We see if we delete this
one the TODO count goes down
but the uncheck count does not
go down since it was checked.
If we delete something that isn't
checked, both of them go down.
And so we have the same behavior as
we did in our React Web application.
Any questions there?
So we have this being a scroll view.
But, if you notice, the
scroll view gets cut off early
and as we add TODOs it grows.
But if we add a bunch of
TODOs it grows with it.
But say we actually wanted the scroll
view to reach all the way to the bottom
no matter how many TODOs were there.
Does anybody know how we
may go about doing that?
The hint being that in order
to control layout what we use
is this thing called Flexbox.
So by default components
will grow to however big
they need to be in order
to fit their children.
But we have a way of saying, hey fill
as much space as you possibly can.
And the way to do that
is saying flex: 1.
And so we want the app container
to have a flex value of 1
so that the app container
fills up all possible space.
And so we could do something like
app container let's do flex: 1.
And then maybe for the TODOs,
the scroll view here, maybe we
want that to fill as well.
And so we could go
down to the scroll view
and say the style is
going to be flex: 1.
But that isn't great design.
What if we wanted instead to just have
a style called Fill, which will just
fill whatever space is available.
And so that would be a
good abstraction to have.
So here we have a TODO container,
we have an app container,
and let's actually create this style
called Fill, which we'll just flex: 1.
And so now we can say hey, we
want this scroll view to fill
and we also want our
app container to fill.
But instead of adding
that to app container,
what would be a better way to do it?
Well, we can actually
apply both those styles.
Does anybody remember how we could
do that, apply multiple styles
to the same component?
So in React Web we would actually
just give it multiple classes.
What is the analog in React Native?
We can actually just pass an array.
And so say first apply
styles.Appcontainer and then apply
styles.fill.
And now, if we add a
bunch of TODOs we can
see that it fills the available space.
And then if we delete TODOs such that
it doesn't fill the available space
we see that it's not getting
cut off at the bottom
because it's filling all the way
down to the bottom of this container.
So any questions on event
handling, styling or moving
React Web to React Native components?
No.
So we've been talking about
this thing called components,
but we haven't really dived too
deeply into what that really means.
In the past few weeks, we've
talked about how components
return a node, how they
represent a discrete piece of UI,
how all components should act like pure
functions with respect to their props.
But that's really where we
stopped talking about components.
And so this week, we're going to
dive more deeply into components
and what components actually are.
And so there are actually
two types of components.
And we've actually seen
both of them already.
So first is this thing called a
stateless functional component.
You might see it abbreviated as SFC or
if you're reading blog posts online,
some people call them pure
functional components.
And what those are
basically just functions.
So something like this
TODO that we've created
is just a function that takes
in props and returns some node.
It has no concept of state.
And so that's why it's called a
stateless functional component.
It's just a function with no state.
And the second is a
react.component which
we've been extending from but we
haven't really talked about it
too far in depth.
And so first let's talk about
stateless functional components.
So this is the simplest
type of component.
You should use this when
you don't need any state.
And what it is is a function that
takes props and returns a node.
And it shouldn't do anything other
than taking props and return a node.
It should be what's
called a pure function.
In other words, it should not have
any side effects, like setting a value
or pushing to an array, updating
an object, something like that
because it should just take
in props and return the value.
If you do stuff other than that you
might create some bugs or even worse
crash your app or something like that.
Then, any changes to the
props that you passed
to a stateless functional
component will automatically
cause that function to be re-invoked.
And then after it re-invokes
the function and returns nodes,
React will do its thing and compare
nodes to what it has in its virtual dom
and then go ahead and
replace what's needed.
And so on the other side of the coin,
we have what's called a React.component.
This is something that's actually
provided by the React library
and implemented for you.
And it's an abstract class that can be
extended to behave however you want.
And so, in our example
here and examples prior,
we've been doing this thing where we
create a class called whatever we want
and we're actually extending this
thing called a React component.
And so what is a React.component?
Well these things have
additional features
that stateless functional
components do not.
One of those, of course, is that they
have instances so they're a class.
And so when you invoke that
class it returns an instance
and that instance will persist
throughout the lifetime of this class.
As suggested by the name,
it maintains its own state
and so stateless components do not,
whereas these React components do.
They have this concept of
state, and we talked about state
in depth last lecture.
One thing we didn't
talk about last lecture
is this thing called a lifecycle,
it's lifecycle methods.
And so these are similar
to hooks or event handlers.
And so we've used the event handlers
before in both React Web and React
Native.
And these things are actually
automatically invoked for you.
You don't have to worry about
exactly the implementation details
or when to invoke your own functions.
That's actually something
that's done automatically.
And so unlike stateless
functional components,
which just take props and return a
node, a React components render function
actually becomes a function of
the props and also any class
properties that exist.
And so if you remember back to last
lecture we talked about classes
and how when you create
a class instance,
you might attach to it some properties.
These properties can be
values anywhere from functions
to just primitives, objects.
And so when you create a
class component instance,
you can actually use all of those
class properties in that render method.
And so we saw that over here
when we created this addTODO
where within the render we referenced
this.addTODO in this button component
here.
And so, as you see, this is a
class property which we actually
used in our render method.
And so this render method is
actually a function of both props
and any class properties like its
state or these methods that we defined.
Cool.
So I talked about this thing
called a lifecycle method,
but what actually is
a component lifecycle.
And so a component lifecycle can
actually be represented by this graph.
And so first a component will
mount and so some lifecycle hooks
get called there, but that's
basically that constructor where
the class instance gets created and
maybe its state gets instantiated.
And then what it does is it renders.
It will just put you to the page.
And then every time we call set
state or get new props we actually
enter what's called an update cycle.
And so when you receive new props,
the component needs to update.
It needs to re-render.
And so part of its lifecycle is
actually updating over and over.
And this happens any time new props
get received because it wouldn't really
make sense if we had
a component that when
it received new props nothing changed.
But also this update cycle happens
every single time the state changes.
So if you call this .setstate, you
update state and presumably you have
something in the UI that also updates.
And so this update
cycle will happen again.
And every single time you update state,
receive new props this update cycle
will fire again.
And then, when it's time for
that component to disappear,
it enters what's called
the unmount stage where
you have the chance to
clean up anything that you
may have created during that lifecycle.
And so what actually does
that mean in practice?
So I said that there's
this thing called mount,
which is basically
just a series of steps
that happens when a component
first gets mounted and rendered.
And so the first thing that happens
is the constructor gets called.
And so, as we saw a few lectures
ago when we talked about classes,
the constructor is where we have
a chance to add class properties
or add anything to that
instance that we need.
And so here we might want to
do stuff like initialize state
or maybe add some other class
properties like bound methods et cetera.
Next what happens is we render, which
is just the meat of the component.
The main goal of any
component is to show you why.
And so, in this render method,
that's exactly what happens.
You take any properties that you have,
any class properties that you have,
and then you end up returning a node.
And then after that this hook,
that we haven't seen yet, gets
called a component div mount.
And this is the chance
for you to do anything
that you wanted to do that
didn't really matter for render.
And so if you have asynched actions,
like standing network or passes.
If you want to add timers
and stuff like that this
is exactly where you should do that.
And then maybe you'll need to
update the state accordingly.
And so if you actually
see that state here
this will cause a re-render
without updating the UI.
And so all of this will happen
before the UI re-renders.
And so let's play with
that a little bit.
So first let's copy this,
that way you can keep it.
So let's clear all of this and then
play with mounting a little bit.
And so in your next project what
you're going to do is you're
going to be implementing
what's called a Pomodoro timer.
And so for those of you who
are aware of what those are--
basically what it is is
a timer that allows you
to switch between two amounts of time.
And so there's this thing called
the Pomodoro Technique which
is used for studying where you study or
work very hard for some amount of time
and then you take a short break.
And then you work hard for
some short amount of time
and then you take a short break.
And so what you're going to be
creating in your next project
is actually a timer that
allows you to do that.
It will automatically track for
you however long you want to work.
And it will also allow
you to set some time
that you want to take a break
in between those working blocks.
And it will do that.
So when you start the timer it will
count down until you're done working.
It will let you know,
hey time for a break.
Then it will switch over
to that break timer,
run down until that ends up and
says, oh now it's time to work,
and it will cycle through that.
And so in order to do
that, you might need
to know how to work things like timers.
And so these methods may be a chance
for you to set up those timers.
And so let's go ahead and
do an example doing that.
So first let's get rid
of all of this stuff.
So in this example we
no longer need TODOs.
And in our render lets
actually just have some count.
Those have a View.
And inside here let's have some text.
And that text is just
going to show some count.
And let's initialize that count to 0.
So, as soon as I get rid of all this, we
have a very simple app and all it does
is show a count of 0.
You see it up in this
left hand corner here.
And let's go ahead and
actually center this.
So let's do styles, and let's
create a new style sheet.
Let's call this app container and
whatever we want to do in here.
So let's have it grow as much as we can.
Let's have it center its items.
And let's have it align its items
the other direction as well.
And down here let's actually pass
this in as styles.appcontainer.
So now we see this
number 0 is very small.
Let's go ahead and make
it a little bit bigger.
And so let's have count and
let's give it a big font
size of like 48 or something.
So now-- style--
we have a big number
and all it does is 0.
And so how are we going
to get it to count?
Well presumably we should
be setting our state
and just have that state increase.
And so if we want to repeat something
what might we use to achieve that?
So do something at some given interval.
We can actually use that set interval.
And so let's first implement this count.
So let's have this
thing called increment.
Is this too small?
Let's have this thing called ink.
And what that does is it does
this.setstate, takes a previous state
and returns the count to be 1
greater than the previous state.
And so now we've implemented this
thing called increment where we
take the states count and increment it.
And so how might we get this increment
call to happen every once in a while?
Well presumably we
should use a thing called
set interval, which we'll call
a function every n milliseconds.
But how are we going
to get that to happen?
Well we should do this after
the component finishes mounting.
We should set up some sort of timer.
And so how do we know or
how do we get a function
to execute after
components finish mounting?
That's actually where this
lifecycle method comes in.
And so there's this
lifecycle method called
componentDidMount which
automatically gets
run for after the component mounts.
And so we can actually set
up our timer tap in there.
And so we can do componentDidMount
and inside of it we can do setInterval
and that's called
this.Increment every second.
And so there's going
to be a small bug here.
Does anybody know what the bug is?
So every 1,000 milliseconds this
thing called this.Increment is getting
called.
And this.Increment is
invoking this.Setstate.
Does anybody see how
that might be a problem?
I'll give you a hint.
It has something to do with this.
And so when this gets executed this
might not mean what this is here.
And so this is a common bug in React.
Oftentimes, when you say
this here, what it means
lexically is not
necessarily what it means
when it actually eventually gets run.
And so how did we go about fixing
this bug in previous lectures?
We have to somehow get this to be
bound to what we want it to be.
And in case we want it
to be bound lexically.
So a few different ways to do that.
One way was creating a new function
here in line that does this.
And I'm actually not sure that
that works in this example
because this isn't necessarily set here.
The way we've generally handled
this is by actually binding it
at creation time.
And so there's a
shorthand whereby we can
say when we create this
increment function automatically
bind it to this class.
And so this is actually a new
addition to the ECMAScript standard
where this is called
class properties whereby
inline as we're declaring
this class we can also
create properties that should
be added during the constructor.
And so this is syntactically
the same as doing this.
Having the increment function
defined as we did before.
And in the constructor
when this is created
doing this.Increment equals
this.Increment.bind whatever
the this context we want to be.
And in this case it's this.
Or in other words, it's
the same as just doing
this.Increment is equal to the anonymous
function that we defined down there.
Whatever.
And so that's just, rather than having
to write everything in the constructor,
we can just use this
shorthand down here which
is just generally the preferred
way because it's easier to read.
And now we've gone ahead and
created this timer that runs.
And so you can see that
the numbers are going up.
And the reason that this is happening
is because we created this increment
function.
We correctly bound it to the
this that we wanted to bind it to
and then we said, hey,
component when you're
done mounting set up this timer, set up
on an interval of 1,000 milliseconds.
So every second call
this increment function.
And what does that
increment function do?
Well it updates the state to be
the previous states count plus 1
and then down in the render
we render this.state.count.
And so you see every second the
state gets updated to a new number,
and the new number is shown there.
And so we never had to manually say
hey, run this code when you mount.
We just created this method called
component.DidMount and React handles
automatically invoking that for
you after the component mounted.
And it's the same as the constructor.
We never had to manually
invoke the constructor.
It just gets called automatically when
a class instance is getting created?
Any questions on the mount cycle or
the mount processor I should say?
Great so now let's talk
about the update cycle.
And so, just like in
the mounting process,
there is a bunch of lifecycle hooks
that got called for you automatically.
There are also a bunch
of lifecycle hooks
that get called automatically every
single time we want to re-render.
And so the first thing
that happens is component
will receive props which
takes the next props.
And so say you had
something in your state
that really depended on
what the props were set to,
you can actually use this function
to update any of those state fields
that rely on the props.
And you do that by
calling this .setstate.
Next is this thing called
shouldComponentUpdate,
which takes the next
props and the next date,
and here you can compare change
values and decide whether or not
you want that component to render.
And you can actually stop
the update cycle here.
And so this is a good optimization.
So say you have a very
complicated component
that takes a really long time
to render you don't necessarily
want it to render every
single time you get a new prop
because it might be that the
new prop doesn't actually
change anything that's shown.
And so you could use this
method to stop it early.
But that adds a lot of
complexity to your app
and there's almost always
a premature optimization.
The next happens render, we
know exactly what happens there.
And last we have this thing
called ComponentDidUpdate,
whereby you can do anything
that isn't needed for the UI,
like network requests,
which is basically
the analog for ComponentDidMount.
And so let's see an
example for this update.
So say rather than just
rendering this text we actually
pass this count to another function.
So let's have this thing called a
count, which takes as a propped account.
And then let's create
this class called count.
And then here, let's first
just render the text.
And so now we're back to where
we started, where we basically
have some text that gets rendered
based on this.PropsAccount,
and let's style it to be larger.
And so now we're basically back
to exactly where we started.
We have this app which
automatically increments
and then it passes whatever its
state count is as the count prop
to this other class that we call count.
And then this component
we basically just take
that prop and render that text.
But say we actually only wanted
to update on odd numbers.
So say we want to create a new--
or say we want to have this
be called CountEvennumbers.
And so, in this example
here, how might we say,
hey don't actually update
unless your number is even?
Right now every single time it
receives a new prop it's updating.
But say we only wanted to count even
numbers, what's some strategy that we
may use in order to skip the
rendering for odd numbers
and only render on even numbers?
AUDIENCE: You could use
[INAUDIBLE] before an update.
SPEAKER 1: Yeah, so we have this
thing called shouldComponentUpdate,
which takes the next props.
And so we have the ability
to look at the next props
and decide whether or
not we want to update,
and if we return false from this
function, the update cycle is over.
It won't render.
And so if in this function we wanted
to check if that count were odd
we can abort early.
And so let's actually do that.
So let's have this method
called shouldComponentUpdate
and first let's just return false.
Now what's going to happen here?
Nothing.
We can see that it's receiving stuff.
So see down here in the logs
we're receiving this thing called
updating every second.
But the UI is just stuck
at 0, it never updates
and that's because we're saying
hey, should the component update?
No we shouldn't.
And so React is saying,
OK, then we're not
going to call this render method
and nothing changes over here.
And so how may we change this is such
that it only counts the even numbers?
Well we can say return, check to see if
the next Props.count is divisible by 2.
And, if it returns true, that
means we're an odd number.
But what we want is whether
we're an even number.
And so we can actually just say,
oh, return the inverse of this.
And now it's only going to
count those even numbers.
Does that make sense?
And so say we wanted to do
something like send a request
or server every single
time this UI updated,
we wouldn't really want to
do that in the render cycle,
we wouldn't really want to do
it in shouldComponentUpdate.
We can actually do that
in ComponentDidUpdate.
And so we can actually do for
now let's just console.log.
We can say, hey, we updated it
and we created a new number.
And as you see, it's only getting
called for those even numbers.
Because first shouldComponentUpdate
gets called and then
it renders and then
ComponentDidUpdate gets called.
And, since we exit early
on all odd numbers,
only the even numbers will reach the
render cycle and ComponentDidUpdate.
And so what you see logged
are only those even numbers.
So does this concept of updating
and methods that automatically
get invoked makes sense to everyone?
AUDIENCE: Could you only
do this kind of stuff
with [INAUDIBLE] and not
the purely functional ones?
SPEAKER 1: Yeah.
So the question was, do these
methods exist on the functional ones?
And they don't because, say
this functional components
are literally just functions.
They take props and they return a node.
And so since they're functions,
all they do are get invoked.
You pass them props and
then you get a node back.
And in order to have
these methods you actually
have to have this
concept of an instance.
And so React components have
instances, and these instances
are tracked throughout their lifecycle.
And since these are class
instances React well
go ahead and invoke
those methods for you.
And so the stateless
functional components
are just functions that
get invoked and do not
have these class methods, whereas
the React components not only have
these methods but the methods also
get invoked automatically for you.
But yeah great question.
So that's the update cycle.
And then lastly we have what's
called the unmount cycle.
There's only one thing that
happens in the unmount cycle.
You have componentWillUnmount which
gives you a chance to clean up.
What do I mean by clean up?
Well, you can remove any event listeners
if you had them in React, mostly Web.
You can invalidate any network
requests that you have out.
Or lastly you should clear
any timeouts or intervals.
And so there's actually some bugs that
you can create if you're not careful.
So let's actually revert
this back to being
just an app that shows that count.
So now we have again that
number being incremented.
And this class called app keeps track
of its own number and is updating.
But say, let's actually
call this counter
and create this thing called app.
And in this, let's actually
just show the component.
So now we have basically
the same exact thing.
So we have this thing
called class app which
just returns an instance of counter.
And counter is what we've
been working on thus far.
It creates an interval and we'll
keep track of that interval
and keep counting up.
But say we actually have this button
that will toggle whether or not
this counter is shown.
And so let's have this
thing called state
and let's have this
flag called show counter
and let's initialize it to true.
And then down here we
can do something like,
if you should show the
counter then return this.
Else let's just return an empty view.
And so now this is basically
the exact same thing
because we have no way to change whether
or not we want to show the counter.
But say we did, so let's
create toggleCounter.
So show counter.
It should be the opposite of what
the previous state show counter was.
And let's also have a button
that will toggle this counter.
And so now we have a button
where if we click it,
we can just toggle whether
or not that counter shows.
And there's actually
a pretty bad bug here.
And that is that when we
toggled this counter--
oops, we should return this--
when you toggle that counter we
never actually tell this component,
hey, stop incrementing.
It's actually going
to keep incrementing.
And so we can show that if
we have here, if we console
that log we see that it's
incrementing, and if we toggle it,
it's still logging.
So counters now gone.
So there's no counter here, it's
gone but it keeps saying increment.
And, if we show it again, now look
at how fast it's incrementing.
It's two every second because
the first counter created
an incrementing function every 1,000
milliseconds and the second time
we created one it also did.
And so what if we did this again.
Toggle and then toggle again.
Now it's going up three every second.
And if we did this a bunch of times,
you see it's going pretty crazy now.
It's like five every second.
And so that's not good.
That's definitely not good at all.
Say you had a super complex app
and hundreds of timers getting set
and you kept toggling them.
Eventually you're going to have a
big problem where a bunch of things
are getting called and nothing
should be getting called.
And so that's like a memory leak and
it could cause your app to crash.
And so how might we
go about solving this?
So, as we alluded to, there's
this thing called an unmount cycle
where we have a chance to clean up.
We can get rid of any
timers that we've created.
And so you can actually do that here.
And so, rather than just
setting the interval,
we should actually track that
function that we created.
And so you can do something like
this.Interval equals setInterval.
And so setInterval actually returns like
an ID of the interval that you created.
And so now we're tracking exactly
the interval that we created.
And we can go ahead and right
before this component dies,
so component will unmount, we
should actually clean that up.
We can actually do clearInterval
and we pass in that ID.
And so now you can see--
oops, things did not get updated.
Let's actually copy all
this and refresh the page.
And so when this loads,
you'll see that it will still
log when it's getting shown.
And so as this number is incrementing we
can see it saying, oh I'm incrementing.
But when we toggle it that
number no longer goes up.
And then, if we toggle it again,
it's going to continue incrementing.
And, if we cancel that,
that incrementing function
is no longer getting called.
And that's because, over here,
when the component was created,
so when the component mounts, we set
the interval for this button increment
to happen every 1,000 seconds.
But then later when we are no
longer returning that counter so
the instance gets unmounted.
It's no longer part of the React tree.
Before it gets unmounted, we say
clear that interval and it clears.
And then when it remounts
it creates a new interval.
And when it gets unmounted again it
goes ahead and clears that interval.
And so now we no longer
have any memory leaks.
So does that whole lifecycle
process make sense to people?
Do you have any questions
about these methods
or why we might want to use them?
Cool.
Let's take a quick five
minute break and then
after this, we'll go ahead and
start writing some React Native.
Hello and welcome back.
So if you are following Snack some
people had some questions about style
and whether or not people
in industry chose to bundle
this style with each component.
And what I tend to
see mostly in industry
is that people do indeed tend to
include the styles with each component
because part of React's
component mindset
is that each component
should be a standalone thing
and it should include with it any event
handlers or JavaScript and any style
as well.
But there are many compelling
reasons to actually remove
the style outside of that component.
And one big compelling reason would
be something like color themes.
So say you had some color theme where
you really liked crimson in your app
and everywhere you were using crimson.
And then say suddenly you wanted
to use something like blue.
If you had everything
hard coded to crimson
it might be a bit of a pain to go
through and find every instance
of that crimson and change it to blue.
But say you actually abstracted
out some value like primary color
and instead used that in
all of your components.
Then if you wanted to change the
primary color from crimson to blue
it would be very easy.
You would just do it in
one file and be done.
So there are definitely compelling
reasons to remove the styles out
of a particular component.
And since React Native uses
JavaScript's objects to style components
it allows you to do stuff like
create variables and import them in.
And so are there reasons
to take the style sheets
outside of any particular component.
But generally if you
have a choice it's easier
to just leave it in there
for organization sake.
Cool.
And so up until now we've been writing
a lot of React Native in this browser
environment.
And so let's actually figure out
and talk about how we actually
write React Native if you were to
start your own personal project
or assignment for the course.
So I've been talking about this
company called Expo quite a bit.
And what they do is they create
a very fast way to build an app.
They provide a lot of
tooling around React
Native and the React native community.
So there are a suite of tools to
accelerate the React Native development
process.
And so one that we've
been using quite a lot
is this thing called Snack,
which is this website here.
We've used it this course,
a lot this lecture and last.
And what that allows us to do is
run React Native in the browser.
So it automatically
bundles any libraries
that we need like React
Native, React, and then
it also runs on a phone
embedded into the browser.
They also give us a tool
called the XDE which
is a GUI, graphical user interface,
to serve share and publish any Expo
projects that you have.
They also give us a command
line interface to do
the same things, to be a command line.
They give us the Expo client which,
if you saw my email from earlier,
is an iPhone app that you can
install and actually run stuff
that you write in Snack or
stuff that you write and manage
by the XDE or the CLI to actually
run it on your phone while developing
and before you publish.
And lastly they give us an
SDK, software development kit,
which bundles and exposes
cross-platform libraries and APIs.
And so included in that are maps, stuff
for like icons and images and SVGs
and maybe animations.
They also give us handy constants.
So the Expo that we imported into
this app is actually the SDK,
and it gave us a constant
like, we didn't use it here
but, the height of the status bar.
And so they give us a
lot of helpful things
to really get our developing
process moving forward.
And so let's take a look at
this thing called the XDE.
So I have it here.
It's a little bit small but
basically what this is is it
allows us to create and run projects.
And so I actually already created
this project before the class,
but when you do create your project
it allows you to choose a template
and basically create the directory
and all of its dependencies
on your computer.
And so, if you started with the blank
like I did and created my new project,
it gives you a chance to
save it wherever you'd like.
But I already went and did that
process and created my new project.
And so, if you want to
follow along at home,
you just do create new project,
blank, save it wherever you like
and then you end up right here.
And basically what this is, is
this is running a bunch of things
behind the scenes including React Native
packager which handles the bundling
and whatnot of your app and any
logs if you want to console log,
will also appear in this XDE.
And so what it's doing is it's
actually looking in that directory
that it created on your computer.
And so if you create it and then CD into
the correct directory on your computer
you end up right here.
And so when you create
a new file you see
this thing called app.json
which is basically
a bunch of metadata that's
created about your project and is
how Expo tracks your app.
And then you see this
thing called app.js.
And that is basically the bare bones
React Native app that you start with.
And when you run it, if you open it
up on a device, you see it run here.
And so this says, open up app.js
to start working on your app.
And if I were to change the text here
and save, we can see it re-bundle.
It's currently building
that new JavaScript bundle
and then you see here, live on the
phone, that you did update that text.
And so, if you want to start
working on your project earlier
or work on any personal projects of
your own, you're welcome to use Expo.
I actually encourage you
to use Expo because they
take a lot of annoying
and difficult parts
about creating projects
and publishing them
and do all the hard work for you
so that all you have to worry about
is writing the JavaScript here.
Cool.
And so we've been doing this thing a
lot in this lecture and previous ones
called importing and exporting.
And we haven't actually
talked about what is.
And so we have talked
a lot about components
and how we should break up components.
And it's actually also highly encouraged
that you break up the components
into their own files.
And so we've seen that components
are great for simplifying your code
and we can actually split
them into their own files.
And then what this allows us to do is
help organize the project even more.
Rather than having everything all
in one big super long file, which
might get very unwieldy, we
can actually organize things
into their own separate files
or even separate folders
so it's easy to find whatever
code you need to update.
Then what we do is from the
file that we create we actually
export the component that we want.
And then we can then import it in to
another file if we want to use it.
And there are a couple different
ways to import and export.
There's this thing
called a default export,
and there's this thing called
a named import and export.
And so what I was typing a
lot earlier is you see me type
this thing called export
default class app.
And that's me saying, hey
from this file here I actually
want to export this app.
And it should be the default export.
And so let's take a look
at what that looks here.
And so in app.js in a brand
new directory I went and--
the boiler plate code says
export this default class app.
But say I want to in a new file.
So let me create a new file called
let's just call it count.js.
From here let's first import from
React, which is something that we
have to do in every single file.
And let's create this
component called Count.
So let's do const Count
equals props and then
let's return this thing called a view.
And then have props.count show.
Actually, let's have this be text.
So this won't actually work because
we're using this component called
Text here which doesn't exist.
So Text here, capital T
capital Text, is a component
but this file has no idea what
Text is, what capital Text is.
It's a component.
We know it's a component because
it's in JSX and capitalized
but nowhere in this file do we
declare this thing called Text.
And so we actually have to import it
from the library called React Native.
And so you've seen me
before in the example
files do this thing called
import Text from React Native.
And what that the actually does is it
goes into that React Native API code
and gives you access to the variable
that they're exporting called Text.
And then when we go
ahead and use it here
the JavaScript knows that
this variable context exists.
And so how are we going to get this
component called Count into our app?
So say I wanted to hear a display
count and passed an account of 0.
So if I save this and
try to run it, it's
going to error because this
variable called Count doesn't exist,
which makes sense right?
In this app.js file we haven't
created a variable called Count.
We actually created it in a
separate file called count.js.
And so as I alluded to, you can
actually export a component from a file
and import it into a new file.
And so we can actually, over here,
just use this term called export.
And if we go ahead and
save this then now we
can try to import this
thing called Count from--
where is it?
Well, it's in the current
directory, so ./Count.js.
And so now if we save that we
can see that it compiles and we
see that 0 show up.
And so let's make it a little bit
bigger so that's easier to see.
And so how are we going to do that?
Let's create this constant called
styles and let's have stylesheet.create.
And let's just have a font size of 72.
And then here let's just do style is
that Styles object that we created.
And if we save this and run
it what's going to happen?
It's going to error.
And why is it erroring?
Well it says cannot find variable called
stylesheet, which makes sense right?
In this file here nowhere is there
a variable called stylesheet.
And so we actually also have to
import that from React Native.
And so if we run that and
save it, lo and behold,
it rhymes and the style is applied.
We see a big number 0 there.
And so that is called a named export.
We exported a named
variable called Count.
And then in here in brackets we say
import all of the variables named Count
that we exported from ./Count.js.
And so that is an example
of a named export.
And say we wanted to export another
named variable we can do export const--
let's just call it num, and
let's have it be the number 50.
And we can, over here, do import
Count and also num count.js.
And then rather than passing
in 0 we can just pass in num.
And as we see over here
now it's the number 50.
Why is that?
Well in Count.js we
exported two variables.
One we called Count,
so capital Count here.
We have a const called Count
and we're exporting that.
And so it's a named variable
that's getting exported.
Over here we have a constant called
num, and we're exporting that,
so there's also a named variable
called num that's getting exported.
Then over here in our
app file we actually
import to this thing
called Count and num.
And so the names do
matter because it needs
to know exactly what we're importing in.
And then we go ahead and use those
and they show up as expected.
And so those are called named
imports and named exports
but there's also this thing
called a default export.
And so you see here we have an
additional term called export default
this value.
And so in our Count file
over here let's get rid of--
or let's not actually
get rid of anything
and let's actually do export
default. And then just
give it a value to export.
So export default this
function that we're creating
and if we want to make this more
obvious what's happening here
we can actually do
const Count equals this.
And then we can do export
default Count, which
is saying set the default
export of this file to be Count.
And then how are we going to import it?
Well, rather than
importing these name things
we just say we want to import
this thing from Count.js.
And since we've dropped
those brackets we
say just import whatever
is default exporting.
And we're going to call it here Count.
And so if you notice it works--
oops as long as I save all
the files but I never--
let's change this back to 0.
And so now as you notice it is
showing that 0 value as expected.
But let's actually call
this something else.
So let's call this custom Count.
So even though over here we're
exporting a variable called
Count, since we're are using
it as a default export,
we can import the default export in
this file and call it whatever you want.
And so we can call it custom Count over
here and it still works as expected.
And so the difference between named
and default exports are that named, 1,
you can export multiple
of named exports and also
import to multiple named
exports from a different file.
And they do have to be named exactly
as they are in the other files.
But when you export
something default you're
limited to only exporting
one which makes sense.
If you exported multiple defaults you
wouldn't know which one to import.
And then over here, you
can call it whatever
you want because it doesn't matter,
it's just the default export.
And so that's how you're
going to go about starting
to remove components from one long
file and move them into separate files.
And so you can also actually import the
export default and also named exports.
So here we are exporting a named export
and we're also having a default export.
And in here we're importing the default
and we're also importing a named export
and, as you see, that works as well.
And so over here you see that we
are importing React from React which
is whatever its default export is.
We could also import one
of its named exports,
and rather than extending
a React.component
we can just extend
component here because we
went ahead and imported the named
export called component from React.
And so that will also work as well.
So any questions on
importing and exporting
and how you would go about
breaking up particular components
into separate files?
Yeah.
AUDIENCE: You were able to access
the components with React.components.
Is that because the component is
[INAUDIBLE] named export and the value
in the React.components?
SPEAKER 1: Yes exactly.
So the question was, I was
able to access component
as React.component and
separately also as component
and that's because this thing
called component is actually
a property on this React.
And so what React exports is
both a default export, which
is this massive thing where one of
its object keys is called a component
and has the value of the component
and it's also separately exporting
a named export called component.
And so we can go ahead and either
import the default export and do that
.component or we can import the
named component and just use that.
So you're absolutely correct.
Any other questions on
importing and exporting?
Cool.
So when we go ahead and
import and export components
they can start to get more and more
complex as we pass down more props.
And so how might we go about
keeping track of all of these props?
Well React actually has a
way to help you with that,
and it's called prop types.
And so React can actually validate
the types of a given components props
at runtime which is great.
It's a development tool that
allows you as a developer
to ensure that you're
passing the props that you
think you're actually passing down.
And so say you're passing
down some prop that's a number
but you actually want it as a string.
It's very easy, as your project scales
up, to kind of get those mixed up
and maybe you pass down
a string when you meant
to pass down a number or vise versa.
And so this thing called PropTypes
allows you to keep track of that.
And React will actually do this
automatically in development mode.
And this is also great because
it helps document your APIs.
And so I have this very simple
component over here called Count
and it takes a single prop called Count.
But say it also took
three other props and say
it also had 10 other components
that also took their own props.
It might get kind of hard to
remember that as I scale the project.
And say you're somebody
like Facebook who
have something like 30,000
different components in production
it would be very painful to
not have those documented
and have to go and read the code to
know exactly what props you should
be passing.
And so by declaring this
thing called PropTypes
you actually can help self
document all of these APIs.
And what's nice is this only
runs in development mode
and so you don't have to
worry about it slowing down
your production in production mode.
And so how might we go about doing that?
There's actually a
package called PropTypes.
It used to be bundled as
part of React but they've
since split it into its own
module though it's still
maintained by Facebook.
So we can go ahead and do this
thing called import PropTypes
from a package called prop-types.
And so now we have access to
this variable called PropTypes
where importing the default export
of whatever this library called
PropTypes is.
And so now we can go ahead
and use that in our file.
And so let's go ahead and do Count.
And so we created this
variable called Count,
which is a function of a
stateless functional component.
And we can actually attached to
it a property called propTypes.
Note that it's a lower case p here.
And I can set it equal to an
object and the keys of this object
will map to whatever
props that I expect.
And so in this case we expect
a single prop called Count.
And so I can say Count should
be of what type, well PropTypes.
So capital P here is referring to
the library that we just imported.
And we can say we want a
number, and it's required.
And so now we see this warning.
We see, hey, there's a
failed prop type here.
The prop count is marked as
required in this component
called Count but it's values undefined.
Why is it undefined?
Well because we're importing
this thing called number
and we're passing this thing
called number over here.
But we're not actually exporting
anything called number in this module.
And say we actually remove
that and passed a 0 here.
Now it'll run as expected.
There are no warnings thrown.
And now let's try simulating a mistake
where rather than passing the number 0
we go ahead and pass the string 0.
The app will still work because we're
just displaying whatever we pass.
But if you notice we
have a warning here.
Warning: Failed prop type.
Invalid prop count of type
string supplied to count.
We were actually expecting a number.
And so that's actually
React's built-in prop type
system which is checking against the
types that we're passing down here.
We say, hey we're expecting
this thing as a number
but since we pass a string it will throw
a warning for us just to let us know,
oh by the way I don't know
if you know this or not,
but you're passing the wrong type down.
And so we can use this thing
called prop types in order
to validate the props that were passed.
And so in stateless
functional components
we actually just add this as a property.
But say this were actually
a class component.
So let's do class Count,
extends React.component.
And then we have a render
which will just return this.
And let's fix some styling
so it's easier to read.
So now we have a class component and
as long as there are no syntax errors--
There's a syntax error
somewhere that I don't see.
Does anybody see the syntax error?
Can anybody beat me to it?
AUDIENCE: Is that last a
parentheses or is that a bracket?
SPEAKER 1: This here is a parentheses.
Oh, yep.
Nice catch.
I owe you some candy.
So now if we go ahead
and reload this, it
can't find the called props
because class component
is stored as this.props.
And now we can go ahead and
see that it is as expected.
We still have that
failed prop type message
because we're passing a string rather
than a number but it's working.
And so we can go ahead and
so we create the class here.
And then we go ahead and do
Count.propTypes here which works.
But generally the way that you
see the convention is actually
to use this thing
called a static method.
And so there's actually a static keyword
where you can do static propTypes
equals that object.
So functionally exactly the same, but
the convention is to use this thing
called a static method
or a static property
because it's just the way that
the new class index works.
And so it's functionally the same
as doing count.propTypes down here,
but the convention is just
to use the newer syntax.
So any questions on PropTypes?
Does everybody see the
utility of using them?
They've definitely saved me
multiple times on personal projects.
And so now, if we've passed the
correct props, there are no warnings.
Great.
And the last concept I wanted to touch
on is just how the heck do I read docs.
Because I can't possibly teach
you every single component
that React Native offers.
But they do offer a
lot of great components
that you may want to use in either
project for this class or maybe
a personal project
that you're working on.
And so here's basically
the steps that I go through
in order to figure out what I should
use when working on my own project.
So first have a goal in mind.
You need to know what problem
you're trying to solve.
Otherwise reading a bunch
about what's offered
doesn't really mean anything to you.
And so say you were doing
something like the TODO app
that we did before the first
thing that you'll notice
is that there is no input
type checkbox in React Native.
And so you have to figure
out what is my goal here?
Well I want to replace
what used to be a checkbox.
And so your goal in that
example would be all right
I need some component that
basically just renders a Boolean.
Then just see what the
library or framework offers.
And so the way I did that was I
just browsed through the docs.
So they're linked in this presentation.
I'll go ahead and link them in
the Resources tab on the website.
But just see exactly what the library
has to offer, see what they have,
then find something that
solves your problem.
There may be multiple things
that solve your problem
but just try to find the thing
that best solves your problem.
And so in my case for that
particular Boolean switch
I saw that they had something
called a switch that
just renders a Boolean flag that you
can just tap and then configure it.
And so the docs will
tell you exactly what
the API is, how you can configure
it, what properties you have to set.
And so for switch we had the value
which was either true or false.
And we had on value change which was, I
believe, the name of the prop that gets
called every single time
you change that value.
And so it just fit that API
to whatever you're using.
And then, of course, if you
have trouble even then, then
you can turn to the community.
A great thing about React,
React Native is the community.
Lots and lots of people use
React, lots and lots of people
use React Native and a
lot of them are experts
who were once beginners themselves.
And everybody remembers when they
were first learning React and React
Native there's just a
lot around and there's
a lot of stuff in the ecosystem.
And the community's really great in
helping each other learn what's around
and how to best solve their problems.
And so just ask the question.
You can ask it in Slack
if you're part of a class.
You can ask it on something like
Stack Overflow or just Google around.
And so if you run into a
problem odds are somebody else
has already run into the problem and
odds are somebody better than you,
better than I have solved that problem.
And you can go ahead
and use their solution.
And so any time you get stuck
feel free to either browse
the documentation yourself or reach
out to the staff with any questions.
And so, yeah, that's all
I have for you today.
Good luck starting your project.
It will be released before next Monday.
