hello and welcome to this react tutorial
where we're going to be looking at
creating a
application that calls the hacker news
api
so this is the application we're going
to be creating
it essentially loads in hacking new
stories uh one by one there's 500 in the
api
the api will return as a list of story
ids and then we're going to call another
api route
that will give us the stories
we're going to be looking at infinite
scrolling this so we can
continuously scroll down and each time
it does that we're going to hit the api
again for another 20 or 30 stories
and then what we're going to be looking
at is
we're going to be testing this with
react testing library
we're going to be using style components
not too extensively but we're going to
be using them just to show you how to
get started with them
um and we're going to be looking at
things like memo in react so we're not
having to recall
well re-render the component each time
on each particular
scroll
so in terms of
this tutorial on you know what exposure
to react you have to have
i'd
say that um
you could come in this from a beginner
standpoint and if you have a little bit
of javascript experience and you have
the ability and knowledge to call apis
you you will follow this tutorial and do
quite well
i don't believe there's many necessary
um
other aspects that you're going to have
to need
essentially all this is is we're gonna
have
one component which is a story and we're
gonna have a container for the entirety
of the stories
so
let's begin uh and we're gonna start by
just creating a create react app with
hack and use tuts
so i'm going to take this one a bit
slower than my last one which was a
todoist one
even though that was a seven hour
tutorial but
this one's going to be focusing on more
of the beginner aspects of react even
though we are going to be throwing stuff
in there like memo
so if we just create a react up
and that will take a few seconds we're
using mpx here
i basically just grabbed this off
the
github of create react up so if you run
this line right here we'll get a react
up ready to go
and we can start modifying it and
playing around adding components in
the only aspects that may get into the
intermediate aspect
of
javascript and
and all on all that good stuff is
the infinite scroll
but i wouldn't worry too too much about
that
let's focus mainly on react here
um so that should be done now so if we
do
our cd into this and it was hack and use
tut
and there we are and i'll open up and if
you want to do this you can go into vs
code and i think if you go to the
settings so i think it's command shift p
and then type path and it should add
code to your path
so here we are that's good
um
let's open this
we'll start by doing a quick cleanup so
generally what i do each time i get one
of these i
go in here we don't need to manifest
um
actually we can probably leave the
manifest in there because we're going to
be looking at stuff like um
service workers and i'll explain those
down the line don't need a description
uh actually it's just
the description
let me make this bigger so you can see
this
hopefully that's a bit better
and we'll say here
we'll just put in some content so when
you're searching google this description
is in the little description descriptive
box below the title so sir bringing you
the finest news
since 2019
uh favicon
don't need theme color we'll keep in
there keep the description
apple touch that's just the logo for the
apple touch icon if you want to make it
an application
or change this to news reader
and my thought process with this
particular application is we're going to
create it now in the aspects of you know
the beginner showing you how again we
into react giving you some nice little
tips here and there like memo style
components uh testing so you should get
on your feet with react through this
tutorial then the next one we're going
to
consolidate a bunch of apis
so we'll get hacking usable maybe we'll
get some stuff from the bbc other tech
websites
uh and then what we're going to do we're
going to use graphql on the back end or
just say
there's middleware to call some services
those services being api routes and then
consolidate those and give us those new
stories back to the front end
um so that should be really nice to do
and that's where we'll get into a bit
more the intermediate
aspects of
react and graphql and we're going to be
writing all our resolvers and everything
else
um
without using anything like prisma
so we've just
got rid of those so we can start by
doing a clean up in here so
generally as uh if you followed my
tutorials in the past you know that i'll
come in here and uh i'll
wipe out the majority of stuff
so we'll just set
export const
bring that into an arrow function
and then down here we'll just we don't
need the return we can just
get rid of that
and say hello and we don't need to
default export here
because we've got an inline export here
that should give us something to
play with
um
let's get rid of
index.css
we don't need the logo number
whilst we're here
we can turn on the service worker
don't worry too much about this at the
moment but we'll i'll explain service
workers as we uh
get to that particular point remove this
um
and what i
generally like to do i just instead of
calling react dom here directly i like
to just remove that and just say give me
render
and then we can get rid of uh
we need to
seeing as though this is no longer a
default input we need to change this
because if you remember in here we're
now using a named export so we need to
use an
um named import here service workers
fine there
um one thing we have to do to turn the
linter on go into your package.json
[Music]
and i generally just remove the es link
config because i like to run the airbnb
one
so as you see it's now running give that
sieve
go in here just add
a equals
remove that there we are if you want to
unregister we don't need that comment
let's open up the sidebar
so now
uh let's have a look do we need to test
not right now we can test that somewhere
else
um close down public we've got app.css
don't need that either it's going to be
using star components
and there we are we've got a clean set
up and
next what we're going to do we'll start
creating the scaffolding so things like
the folders
and this is a really important part of
software development
i want you to get in the into the uh
the routine of creating these folders
where you have separations of concerns
so you have components folder containers
folder hooks folder
selectors mappers all this stuff that
transforms your data and keeps it
separate so it can live by itself
um so i'll show you that right now
okay so one thing i've just set up now
is um
well what i want to do
let's just begin and start this and just
make sure we've got something coming out
generally you may see this issue where
it's like
telling it telling you about skip
pre-flight check there is
so if you do see that issue go ahead in
here
um
and just create a new file
dim put that in there
and then if we go ahead and restart that
we should to get the application
starting
let's see
come on
there we go perfect
so let's begin by doing the scaffolding
for the app so let's do components which
is a folder or just house our components
we will then have constants
and generally this stuff is in uh most
large applications um because you want
separation of concerns so stuff can live
by itself
hooks we're going to need a services
folder for the um
api calls
a styles folder for our styles
uh utilities folder which will basically
just house stuff that is kind of
miscellaneous
uh mappers
selectors
and that should be it for now uh even uh
only containers let's do a containers
folder
so that should be good so let's begin
like what do we need to uh you know
start hitting the api
well
let's have a look so github
um
and then what we want to look for is
the hacking news api
so this is a hacking news api
and it just gives you
let's have a look
these uh this is hacking news and we're
just going to be calling this api
and they've got this api here
um
we'd have to worry about all this
particular stuff right now
and uh
if we click on one of these you can see
that it returns to some json data with
like the title the story the url
but like i said we have to worry about
um right at this moment
what we want to worry about here is this
new top and best stories so up to 500
topper news stories are available at top
stories news
news stories and best stories we're
going to be wanting to hit the new
stories
so
we need some sort of service
that can hit this new stories
so as we can see it returns ids and
these ids are story ids
and what we want to do without these ids
is get them back and it's going to give
us 500 so we've got to be a bit careful
in terms of how we're going to manage
these api calls
but what we want to do is we're going to
get these 500 back
and we want to render 20 or 30 of them
per scroll
so to begin with we're going to get the
500 stories from the api which is this
so this is the url i'm going to be
calling with axios
and then say we got this one here
2906
62655
we want to go ahead and it says for
example a story lives here
so if we change this item to
this url you'll get all this data
and that's pretty much all we're going
to be doing so we're going to do two api
calls um well two routes we'll be
creating two service container routes
and we're gonna be calling this api um
for the stories because we only need to
call this one this api route once
because we only need all the new story
ids in this case it's top stories but
you can do that new stories
and we'll get all the ids and make api
calls to
with these ids to get the story
so that yeah that's pretty much it
really um i guess what we need to do
next is let's have a look
we need to create a new tab in here
a little bit bigger and what's going to
do yarn add axios
and axios is a nice little package it's
not react specific
but it's a nice package that allows us
to do
api calls and essentially it's it's just
what fetch is doing
but um people seem to prefer it i like
the package
uh you can have a look just do github
actually austin has tons of useful
methods in there
so now we've got axios we can actually
start making calls so if we go back in
here
i mentioned the services folder earlier
let's create a file let's call it hn for
i can use api.json api.json.json.js
and we'll import axios
from
axios
and then what i'll do
we want to create some sort of base url
that we're going to be hitting so if we
do export const base url
let's leave it empty for now
and then we're going to do expert const
new stories
url
and let's put that to an r
and then what we're going to do we're
going to do xbox cons story url
and we'll build these up
so for example i'm going to make these
into 10 template strings
um we want to include the base url here
so base url
and then what i imagine that one will be
is new stories so you could switch this
out if you if you wanted to not be a
json and
pretty much the same here base url
and we're going to say i am slash so
let's go get the base url
so the base url is this here
right up to there and you see i've got
item there
that corresponds
with this one here so if i just paste
that in here
now this is saying this story url is
saying
this particular string lives in here
and then item
likewise with this one
so now we can start creating a function
that will
get me a story so
let's test this so actually you know
what let's get the story of our story
urls first or story ids
so export cons because we're going to be
using this through our application so we
want to import it
so say get story
and that name is perfect something like
that is exactly what you want and this
is making some sort of side effect
so when you think of stuff like image
processing so if you're on twitter
you upload an image on facebook and you
can crop the photos
it's quite heavy likewise with network
calls which is what we're doing here
um
likewise with accessing the file system
it's going to block say the rendering of
the ui so we have to use async here
and by saying async
we're going to shove it onto something
called the micro task queue i don't want
to get too
deep into exactly what the micro task
queue is right now but i'll tell you how
it works when we call this
so
if we do cons result and we're going to
say
await this response from axios
and we're going to this is going to be a
get
and if you look at axios you've got all
these um
different methods so you can have delete
get
should be post patch
put requests so there's all these
methods but we're going to use get we're
going to say go get me that data
new stories url
and what we're going to say then is
once
you've gone and got me this
then
get me
the data and we're just going to call
this data
and once you have that data just return
it
um we don't need this actually
so i've just said okay now you've got
data pass me return me that data
i'm gonna say return result
and if i just go ahead now and go into
app
let's start
bringing some things in here so we can
test it so
um yeah sorry not up uh let's close that
down open this up
actually you know what we can test we
can test this directly and up it'll give
us a good understanding of why we don't
want it in app we just want app to call
one container or one component and then
go do all the business that you have to
do in that particular file but right now
let's just call in here
so say
return
hello but in here we want to use
something from react called
use effect
in addition we also want to use
state
so if i now just saying here
um when this application you know gets
mounted to the page as in you can see
what's on
the page
we want to call our api
immediately but we don't want to be
blocking the ui so we still want we
still want the ui to be interactive
so what we're going to do to mitigate
that issue is
we're going to hold something in a value
so we're going to say used
and if you've not come across hooks in
react just yet let's just say
we want the story ids to be stored in
this variable here so story ids and if i
ever want to change
story ids i'm going to have to use this
one here so set story ids so you've got
a value and you've got a setter which is
essentially a function
that you can
pass
data and we know this is coming back as
an array
because if i hit
this here there's an example here you
see the array
but just for some sanity let's have a
look there you are you got an array
so i'm just going to say okay if nothing
comes back or initialize
this particular variable here story ids
as soon as you this loads
i want you to assign
an empty array to it
so for example if we don't have the data
and we start looping over that
and it's not an array we're going to get
some sort of error and we don't want
that so we're just going to say give me
initialize that particular bit of data
with an empty ray
so just to recap we have a variable here
that's going to be initialized to
the empty array and if we ever want to
change this we just call set story ids
so this is where the magic comes in now
so we've done the the work in this hack
news api we've got this we're making a
call out to the hack news api
we're using axios so we want to call
this in here and we can see that it's a
named expert so we're going to have to
use a named import to grab this from the
hacking news api
so let's go ahead and set imp
and i'll say
um what did i call this
uh get story ids
and we know we're gonna have to go
outside the folder and we're gonna say
go get me
services
uh let's just services
um
hn api serve that
then we're gonna say
use effect
okay so this is where the big one comes
in what exactly is use effect we've
looked at use state where you can store
values
so like this is stored to this initial
array to begin with but if somewhere in
my render
or somewhere in this use effect i want
to update this value story ids i can
call this and say
um
set story ids hello
so there we are
that will now be hello oops
so let's just see what happens here so
if i log out hello
so if you want to call story ids you can
just say story ids
let's see what happens here
cannot resolve
i can use to module let's take a look
what's going on
uh services i can use api
uh let's see
services get story ids
don't spell that right
i did
that seems right so let's have a look
what's going on and this is what you're
going to be running into so if you are
a a new program and you you think these
tutorials always go fine i see people
programming
um
[Music]
let me just get rid of that a second and
you think you know how can the get
through that so easily it's never the
case uh stuff always goes wrong
and i think it's best to keep somewhat
of it in tutorials so set story ideas to
hello
so there we are we got hello there
oh yeah so what happens if
i wanted to change this so if i just get
rid of this and i'll still you know
uh
print that out
what do you think that's going to be
it's just going to be an empty rear and
you can let's have a look let's
stringify this
and there we are it's an empty rear
so that allows us to have some sanity
check so if i just bring back in
import
get story ids from
services
i can use api
and then say for example
i want to call this
method now that we've put together we've
done all the work in here i just want to
call this now
so i can just simply because it's a bit
it's been imported up here i can just
say
guess story ids
like sir but what we gotta do
oops
i'm putting that inside the uh
well what say well that is just yet but
i'll tell you in a second
let's have a look bubble lord i cannot
find
services can't resolve services
let's take a look
so we've run into the same era as before
so i'm thinking that it is well
it's not very descriptive is it so we
are doing expert const
get story ids return result
and we're getting that from
the hack and use api
so module not found cannot resolve
in
i can use tut
so even though it's coming through here
and it's all looking fine the module's
fine
so i don't know if this is a case of
let me restart this
start in
it's taking its time
that's fine so it works i don't know
what the issue was there
um so yeah we've got the story ids and
uh if i let me log this out
um because i want to make a few
important notes about what's going on
yeah so you see it says promise but you
know i thought it was returning me my
data you see the status is resolved the
value and we've got a bunch of data in
there from the api so there's 500 um ids
in as you can see there
but why is that happening
well you see how we've stuck this async
on here so any function that you stick
in async on will always return a promise
so now what we have to do we have to go
back to app.js and say
we can't just call this directly that
like we just did then like a regular
function we have to say okay once the
data's there
you see how it's giving me these options
so it's saying attaches callbacks for
the resolution and or rejection of the
promise so i'm gonna say okay go get me
those ids
and then return me
the result which will be a promise
with the data held in there and we have
to resolve that promise
so we can say and to resolve it we can
just say then
and by saying then
on this particular um
return promise here because it's
asynchronous remember it's asynchronous
and the big no is like i just mentioned
it always returns a promise
so you say get story ids dot then i'm
gonna say okay give me the data
and this could be anything
i could say
lemons
so once you have the lemons
go ahead
and set story ids and by calling set
story ids here we're going to replace
this
empty initialized array
with our 500 story ids
how cool is that so let's take a look
set story ids with lemons like i said
you can call it anything
well change it obviously but um you know
boom what's going on here object not
great that's perfect so when you do see
this objects are not valid as react
children we know it's well i know it's
worked um
and i'll show you why uh in a second and
why that happens because you have to get
used to reading these errors
boom you see that so you initialize it
you initialize it quick it's an empty
rear
and then it returns you all this data
but you have some issues here right
so this is saying it's giving me all the
data back from axios and i don't want
that
so let me go back and say okay so we've
got um
well what we've got here we've got our
lemons so we're getting the story ids
and we're saying dot then
now it's saying uh it will say here so
on fulfills
once you have the lemons uh you know you
can return the lemons if you like
but what i actually want to do
you know i know the lemons are going to
be there so i can just remove that so
i'm going to say get me the story ids
over here i'm going to call this i know
it's asynchronous because i put
asynchronous there thus being
asynchronous it's going to always return
me a promise
and in there you'll have promised value
which will
be holding your data because we did it
here
we got the
returned it
once this is done go back so we're away
in this context here so it's
going to await this response then it's
going to pop it into result
and
then we call it
then we're going to say then give me the
lemons set the story ids to lemons
uh let's have a look what's going on
here so uh
we're getting all this data back so
let me just take a quick look at this
um
you can inspect it so we've got all
these story ids as you can see we've got
500 and they all we also get returned
the uh the response and a few other
things from the hacking news api but
like i said we don't want those um
basically what we want
is a um
a clean
a clean array so let's have a look so
we've got the result we're awaiting the
result axios.get
new story url then they're
there
so i don't know if you can see the error
here what's not a particular error but
it's kind of a clean up axios is re
returning me something called data or
i'm assigning it to data
um oh in this case it actually is
returning me dirty so you see there
well i only want the data i don't want
all this other stuff here like the
content type
the headers none of that none of that
nonsense
so a way to do this is i know that's
called data because i just saw it in the
console and i want to structure that out
in a nice easy clean way to do this
open up
one of these one of these uh curly
braces
um i always forget the name then another
curly brace or should i say bracket open
up the bracket give it a curly brace
and then you know basically what we've
created is this
and what that's saying is the structure
me out data i only want data
as in that particular value
as you see now nice and clean and if you
look into the the the uh dev tools
all you've got in here is just all
the um
uh 500 top stories uh ids and if you
call one of these you'll get the article
not the article itself but you get like
the title the link all that good stuff
so let's go back
so now we've got lemons and i've shown
you you can call it anything let's
replace that with data just so someone
don't come in and think all right
you know some some guy here is getting
some lemons from a hacking news api
which is a bit strange
um so i want to just take a quick a a
quick look now at um use effect and
we'll start
basically we'll start refactoring this
putting it into its own container
uh because this is far too hot the
far too high up the reactory to be doing
all this re-rendering if you leave
something in app that has
accessories re-rendering components down
the line you don't be re-rendering 500
components or all the components below
so we're going to put it into something
else um
but now
we've used effect you'll notice you've
got this use effect function here
that um return well it's saying okay
i've got an anonymous function and go
ahead and do this and people may be
asking oh why haven't you got an async
stuck on here because you know this is
you know it's a network call well
there's no reason to use an async here
because what we're doing here is this is
returning me a promise so it's still sat
on this little queue called the micro
task queue
and uh once i resolve that it's going to
get popped off that queue and get um
whipped around the event loop and say
okay put me back in and so there's no
need to stick an async on there
hopefully that makes sense because we've
already done the async here we get
return to promise all we've got to do
then is just resolve it
and that's what we've done there you can
obviously put other stuff on there like
um catch uh you could wrap this in a try
catch or you could put an error on there
whatever it may be but we're just using
then we're just saying resolve this give
me the data once data's here
i'm gonna set it and that's it we're
totally done with you that's it we're
done
uh but let's go back to this here so
what are what is this empty array
essentially in the shoe's effect like
why is it just stuck around here can why
can't it just be like this well this is
a life cycle if if you were prior to you
know uh hooks uh using react prior to
hooks you'll know that you had life
cycle methods in react and basically
what this is saying it's saying okay
uh
when the component mounts
uh do this
um if i put in there um
let's say for example we had a variable
i was like story ids
updated and what it just basically was
true or false
um we could keep a watch on this so i
could put story ids updated in here
and basically use effect will watch for
this to change so if i passed
maybe a set timeout so set timeout which
i'd never do but um if i every 10
seconds even though this is never
accurate in terms of the reading of the
seconds it's basically saying do this
for a minimum of that amount of seconds
so if you have two thousand milliseconds
it's saying do this for a minimum of two
thousand milliseconds
but let's say for example in here every
two thousand milliseconds
i you know did story ids updated equal
to true
um and then i'd you know eventually kept
switching it between true and false
and this use effect will see that and
then it will be like okay well this
story id is updated has changed i need
to rerun this again
and when it reruns that it will do a
re-render and you know potentially we
could have new story id so we could get
new stories so we could have a live feed
of new stories so all that does is with
an empty array it's just going to run
just the ones you stick something in
there
and it's going to watch
that particular
variable and if that variable changes
it's going to re-render so you can run
into an infinite loop here if you're not
careful and i'll show you why
so uh while whilst this is happening
i'll just uh
use
effect here so let's just watch how it
works you know if you want to learn
react just uh or any language well
javascript merely dump a bunch of
console.logs in there and just see
what's going on in the dev tools
uh so let's have a look console.log
use effect here you see you just run the
once
great right
okay now let's run into an infinite loop
um because we love infinite loops so i'm
gonna stick story ids in there so this
is going to run
and it's going to be like okay well i'm
going to set the story ids with data
oops i'm going to set the story ids with
dare and this is watching story ids so
it's like okay well story ids have just
changed i need to re-render this
and when it gets here again it's going
to re-render well it's going to set the
story ids once more up here
and then this is going to be like oh
well story ids have changed again
i need to re redo this function and just
keep going round and round and round
because
once this is resolved
we're gonna basically say set the story
ids
the use effect is watching the story ids
and it's gonna come back in here keep
re-rendering and we'll show it uh i may
crash my uh tab doing this but uh there
you are look at that it's going crazy 25
it's just re-rendering i think chrome
should have stopped it no it doesn't i
think firefox does though um so i need
to check that out i'm gonna
my laptop may set on fire
um
there we are
perfect we're back to normal um yes
knowing for not loops there but yeah
that's how use effect works here's
another way to
what we're looking at later so we'll be
looking at clean up
and cleanup basically is when you want
to just clean up anything some sort of
subscription or something like a layout
effects so if you're messing with the
layout like a um
you call in a scroller you don't want to
be
re-rendering um all the time and because
there's implications to that but i'll
explain why there but now now we've got
the um
uh story ids
i want to refactor this out and say okay
give me a container and i'm going to
call this container
oops not a new folder i want to call
this container
um
what we're going to call it uh well
let's just let's just do it in plain
english it's a story's container let's
just do stories container um
i think i think that's as simple as you
can get with that to be honest uh so
let's grab this off here stories we're
gonna need react um
we've got to go up one more for that
and we're going to need we're going to
basically need this all right
so if i just put this right back to
normal um
come on you can do this
oops there we are that looks good to me
uh we'll just bring that in oops just
bring that in there
that looks good rename this uh in here
to uh star is container
star is container
um stringify looks good
uh and then you know what i'm gonna
render that story concerner
stories container
and where did we put it well we put it
in containers
um
because it's next to it let's go
stories container
soon as though this is a component you
know what render that component
there we are
perfect nice refactor
um
so now we have
a
our
story storage container and we've got
all the ids
what we need to do now is create um well
essentially we want to be able to pass
an id up to the hack news api
and
we're going to be doing in here so let's
do xbox const and instead of get story
ids let's go set get story and this is
an asynchronous function
that takes in a story id
and then we're going to say const result
pretty much the same as before
await axios
dot get
and we're going to give it a template
string and we're going to say story url
which is this here so we're going to say
okay give me this
and then just item for on on the end
which is good
and then we're going to say plus
actually not plus i'm living in the old
world of javascript here
um let's just uh actually we could do a
plus uh story id
um there's other ways to do it template
strings but we'll just we'll do that for
now and said.json
and then of course we have to resolve
this so let's do dot then and you can
see how the uh the intellisense is
telling me you're gonna have to resolve
this we'll do the same as we did before
let's just structured data out of there
and once we've got the data we're gonna
say give me the dare
return the data
that's all we're doing and you know what
we need to return this result
because now this is a promise that gets
returned we're going to have to
you know let's test it um what we've got
here it's called get star is
um
let's see
we could actually just do
uh we'll say if stories ids and story
ids is
dot length is greater than zero because
firstly it's not going to be there
actually let me just show you the
implications of passing an id right up
there
let's grab this one
um what do we expect it to be
let's switch out that id
so expect it to be
i don't know what that is um
but anyways let's pass it this idea
uh so yeah we're passing it this id we
can just actually pass it down like that
and now let's resolve it
um and always say console.log
there looks good to me
boom there it is
there's the story
and you see it matches up with this
perfect
so we know that works which is great so
we've basically just built a service in
here that can
call um the hacking users api and that's
all it is that's all that is for the api
uh so pretty simple right really nice we
can get data from elsewhere
and uh we obviously have to build on top
of this so
at some point in time we're gonna have
to build a uh a story
so let's take a look now what else we
can start working on we've got our story
ids and we've also got our stories well
we can get a story which is which is
really good
so let's go ahead and
quickly take a look so if we just hop
back
um let's have a look
we've got the story ids
so
let me see here um i guess what we want
to do from this point
uh let's see
um
we want to start building out the
well the app's gone
so what components let's create a
story.js component
and here import react
and then let's go ahead and
do expo
const
story
and then we'll say
return
[Music]
so let's see we've got the return um if
we just dump something in here actually
let's pull in
um use the use effect
let's see
and then we'll do the standard stuff use
effect we know how that works now what
we do want is we want
uh get story
and in that get story we want to get
from services and i can use api
um
let's see so story returns and we'll
just say
i am a story
so look at this save that story
container
so in story container what we're going
to be doing is we're going to be looping
over these stories so we've got 500
um
so let's just uh loop over these and
we'll do
uh let's just
story ids
dart map
and what's there for each story id so
when we're mapping over
it's going to give us a story id again
this could be anything this could be
lemon
piece or whatever it may be but let's
just call it story id because that makes
sense
and then we'll say give me
what should we give me
give me the story component
let's import that
and that's a story so it's a component
and it's our story component
and that lives in components
and we're importing this as a named
input because
we exploit it as a
named export so we have to do as a named
input
so let's have a look here so this
let's pass story id as a prop
so for every story component that gets
rendered on the page
we're going to pass the story id
and this is one of those
let's have a look i'm sorry i'm a story
i'm a story cool
but what this story id is gonna be if we
just serve this and go back and pass
this in here
we can say story id let's just have a
look what that story ideas
there we are perfect so we get the story
id and that means we can now use that
story id to make a call
over to the hacking news api again to
get the story information back
and if you're coming from two
traditional backgrounds where you've got
parameters and um or well arguments so
you can pass an argument into story
you would probably see something like
this
but seeing as though this is not a
function well in some ways it's a
functional component
which it actually is
but we cannot use the parameter as such
we have to
the structure that out
like so by giving curly brackets and the
reason for this is uh in react
um
so let's have a look so we get story
ideas here story ideas come through
um
let's see
what they were coming through
ah okay so the story id is sir
justin.stringify
did i crush it because that's rendering
now 500 components
uh objects are not valid as react
children object with key story id
there we are
so we've got the story ids but let's say
for example sick we just call this props
and we don't just structure anything out
of there
and i'll just remove this
um and we'll do
console.log not console.log i want to be
able to see it on the page so i'll just
say stringify props
let's take a look
there we are you see here so basically
all we're doing is just structuring our
story id which will give us this
so let's put that back to normal
and you'll see that pattern everywhere
in react it's it basically saves you
from having to do props dot
story id which is uh
quite long-winded
um
story id
so now
what we want to do is
we want to make a call and seeing as
though we've already built this get
story
we're just going to pretty much follow
the same method we've done here where
we're doing and get story ids
and then place it into story ids but
instead
we're going to say ustear
and within you state what we're going to
do we're going to call this story
let's do that once more used
story
set story and the initial story we're
just going to say it's an empty object
so within our use effect
we can come down here
and we can say get story from in here
which will be this
and then we can pass it the story id
which is basically just this uh prop
that gets passed down
and then we'll resolve this asynchronous
function and said data
and sometimes on this api i've seen that
the dot com with urls
so i'm just going to say okay once we've
got the data
once it's been resolved and you know
you've got the data in here i'm not just
going to return it i'm going to say and
and
to make sure that we have a data.url and
if we do have a data.url we're going to
set story to data
and that's pretty much it
and you don't have to watch for a story
id changing
so in this case i'm just going to
disable that eslint rule
because the the fact of the matter is
here is
um this story id even even though it's
uh
it's kind of component based where we
only need it once
we need this story id once and that's
pretty much it
um we don't expect it to change maybe if
there's comments on there
um but in this case it's not but if
there's comments on there we could watch
the comments changing and then we'll
recall the api to get updated comments
for example but in this case we don't so
we're not going to watch for anything
we're just going to say
as soon as this component mounts
do
this
which gets the story and we pass it
starter id
then it gets
resolves the the function gives us data
and then we're going to do a check for
the url and then if all is good at that
point set the story
um so now let's have a look so we should
have a story
so let's just
json.stringify
story and it won't be there immediately
let's take a look it won't be there
immediately
but there you see them loading in
perfect we've got an empty one here
which we can resolve later by just
making sure that
uh we filter our empty ones
and another one there we see how the
stories come in
and there's quite a lot of them
there we go perfect
so now we've jumped back in here we can
start just building up this component so
we can just say
if there's a story so this will get rid
of that you know empty object and well
this bit will and story.url
then go ahead and just say
give it a p tag and just say story.
story.title
and we want to execute this as
javascript we don't just want to give it
some p tags so that's why i'm just
wrapping in these curly braces
story.title and we'll put this actually
in
href
because we want the url
so it says story.url
and then from here or now we what else
do we have um we have story.buy
um
so we can set
by
uh
was it story.time
we can come and fix that let it post it
and we'll just say that i got posted
time
um
i don't believe we have much more so we
can just take a look at that right now
um let's see
let's see what we've done wrong oh
always have to return something in the
render so even in this case
i'm just going to return null which is
fine
we said bye yeah there we are there
and that's what we was looking for
that's how simple is to make the api
calls
and we get this complaint in here so
each child in the list must have a
unique key prop so we can fix that by
going into
story.container because that's where
it's coming from stories container
grab this
story id because we know that's never
going to change
and this is how react checks for updates
as well to see what should be updated
and in what particular position so if
you look at reconciliation within react
there's a good post on the react
documentation about how reconciliation
works and why the key prop is very
valuable so if this is changing
don't put it in the key so if you're
using something like math.random it's a
it's a bad thing to use because
when it's looking for changes it's like
oh the story id has changed even though
probably the component data hasn't but
it will re
um
refresh all the stuff in there and the
positioning for example
on a list could be wrong but
nevertheless i don't digress into that
just have a look
as to how that works
so we've got our stories now
there's no null ones which is good
uh we don't need to get story in here
for the story container
um
[Music]
let's have a look where we're at now we
don't have any hooks mappers
um one thing i do want to
create is um
something to handle what comes back from
the api so
if we just take a quick look as to
so what's in
just remove this quickly for one second
and actually
remove all that
no
nope
uh json.stringify
and we'll say story because it's instead
now
so i'm just logging out what's inside i
just want to see
what's in there
and you see how we've got descendants we
have
whoops this is quite a lot you know
we've got descendants okay let's just
use this as a uh example type we don't
care about the type we don't care about
the descendants
uh the score so we're going to get rid
of that
so when this comes back from here
we don't want to do it at this
particular level we'll do it in get
story but
let's take a look in get story
and what we're going to do we want some
sort of function
that selects the fields
nicely so we'll say select
uh fields and we'll just wrap that
and it's going to say okay well it's not
defined
okay i understand that so if we're going
to utils
we could just call this select
fields.js
now within selectfields.js let's just do
export const
and then we'll call this select fields
and then we'll give it a function
that the structures our id by url time
title
and then we'll say okay if this stuff's
you know if it comes in and there's uh
there's an occurrence that this
potentially could be empty
so for example let me just finish this
function let's say
return mean object with id by
url time
title
and there we go so we've got select
fields so that should just bring us back
this stuff now we shouldn't have like
descendants or scores or anything like
that
um
but if we pass something in here that
just happens to be like undefined let's
uh default it to an empty object
so that's that file done select fields
we need to import it in here now so just
set imp
select fields
from utils select fields
perfect
let's go back
and we can actually test this
by just
heading
out
that wasn't good we can just test this
by um
coming in here
json.string fight and let's see if we
have the descendants
as far as i can tell there's no
descendants in there which is good
so i'll put that back to normal we
should have the stories going in
um
[Music]
let's see yes we do perfect
okay so we've got the story container
we've got the
oh cannot destructure
id of undefined or null where's this
happening select fields
so we have to make sure that
when we're actually passing into
that select fields that we're not
getting
anything that's potentially going to be
null
so if we open up the hack and use api
we'll say okay once you've got the data
uh we're gonna set data and
which basically says okay if it's not
null and it's true for value go ahead
and pass it into there and then we will
run into that issue
that's the hacking news api part
finished
we want to implement um
infinite scrolling test but we're going
to look at that a bit later down the
line
but one thing i want to show you right
now is
um well one thing i want to work on
right now i think
this looks quite boring so i want to
give it a few styles and
you know just make it a bit nicer so
let's go ahead and add in
styled components because that's what
we're going to be working with
we're not going to go too complex as i
said at the start of this tutorial
let's add that but um we're going to be
looking at how you can just manage props
and stuff
um
and changeability within style
components
uh but yeah we'll see we'll see if uh
how how it goes i do like um you know
sass so
not fully switched on star components
just yet but we'll see
uh so we've got style components now so
we can actually
let's start doing the
um see
if we got styles folder yes we do
so let's call this story
styles
dot js
and within here let's just say input
styled from
style
components and do export const and the
way style components work is it gives
you back like a component
somewhat of a wrapper but it's more of a
component so if you've got let's say we
call this story wrapper
and we'll say styles because you always
have to give it this um con styled which
is the interface so we'll say style dot
and we'll give it like the
um
semantic markup so we're gonna say
section
and then template tags
and then just do whatever you want in
here so we'll say okay padding top which
is 10.
uh margin bottom i'm going to need a
margin but i'm on the story wrapper
border top 1px solid and we've got cccc
i'm gonna say okay first of type i know
we're gonna probably have issues with
when we've got a title we don't want a
border on the top one
likewise last of type
let's remove that
we'll say margin bottom
zero padding bottom zero
that looks good to me
so let's import that and just see how it
looks
one thing i want to do story
uh
stories container i think in here we
need some sort of um
i don't know maybe some titles as to
what's going on right now i'm just gonna
call it
so we've got the map
right now i'm going to call it hacking
news api but like i said in the next
tutorial after this one we're going to
be using graphql and grabbing a bunch of
different news
apis and we can and that'll be really
interesting to see how we can use
graphql as the the man
in there and we can create services
around that
so let's just give this a fragment which
allows us to render siblings next to
each other and don't get confused by
this it's just saying okay we can render
two components next to each other like
component one component two
but you cannot pass any props to this
fragment if you want that you want the
react.fragment1
and then you can pass like a key value
but
let's just uh let's not digress we'll
give it a fragment
uh i'll chuck this in as some javascript
and then also what i want to do here is
um
i'll just give this h1 that says hacker
news stories
uh let's see where we're at so the
hacking news stories and then
let's see
[Music]
we have the map
where what's this winging up
unterminated json contents
uh
no let's see
i've lot i've gone into bracket hell
oh
no stop
there we are
uh this is what so what's this saying
here expected uh unreachable card
uh what's unreachable
oh
the lintzer is not serving me today
there we are
so let's have a look hacking new stories
and there they are loading in perfect so
let's go ahead and grab our styles it's
called stor story wrapper in this case
so what we want to do now is uh we want
to go ahead and import this also input
story wrapper from styles
story styles
and down here let's just basically
rebuild
a bit of this
so we know we're going to be testing
this later on so let's say story wrapper
and we'll give it a test id of story
just to make sure it's there
starter wrapper
and let's just see where we've got we've
got to with that
come on
okay so we've got a bit of padding
you'll see it's been injected
you see it gives it a class a class name
which is nice and gives it some weird
class name but
it's quite cool how it does that
so let's go back into our story styles i
don't know if we want to do too much
more in here i know we've got actual we
do have uh two other things to do we've
got a title and we also have the meta so
like
time and buy
so let's do xbox const and we'll say
story title
and within that title we just want some
fairly generic but we'll say style.h1
again we're using this semantic
tag
inside.h1.section you could in here do
you know div or whatever it may be
and then let's
margin bottom 5px
let's just pull this up here
size 18 px line height
1.8
give it a margin of zero
text decoration none give it
a color of two two two two
is it two two two e two e two c maybe is
that the one
background color
four eight
dc 3d
text decoration
none
and then we've got the meta in here too
so also
we'll go pretty much of with the same
routine so story meta we've got
style.div
um
let's have a look
we want font style italic so when you've
got stuff stuff like
the
by uh the author which is going to make
that italic and since we've give it
we'll give it a span or say
which is not the first child but before
that child
give me some content of
oh let me just go grab the bullet snip
it from
my snippets content um
snip its total box
there we are let me put that on a
keyboard shot cause i use it all the
time margin bottom margin right margin
left
uh you could actually just do for this
you could probably for shorthand css you
could do
zero so i'll target top and bottom this
will target left and right
and then we'll say story we're gonna use
bem still story bold
and we're bold
uh i think we should be good but we can
test this i normally just write out a
bunch of css and test it after and we'll
say it's going to have a meta element
which will be our spans
and then we'll say font went bold and
this is probably the furthest we're
going to get in terms of complexity with
style components but we'll just say okay
if there's a color and we pass some
props
to that
we'll say
props dot color
so if that exists or you're gonna give
it a red color
and that's
one of the uh aspects of style
components you can pass props in so if i
was to use
story element
story meta element and passing
color
um i guess you could just pass
uh ffff for white
that would give it the white color if
not it would just if i didn't pass it in
it give it red
so we can have a look so the star
components there i'll move the story
just one tab over
um
so we've got in here now we've got story
title so let's take this
and pretty much what we're going to do
we're just going to start replacing what
we've already got so
let's do story title
and we'd no longer need p tags in here
get rid of those
that looks good to me
and we've got the story wrapper so let's
just say okay we're already importing
from story style so let's just go back
and say give me the story title two
give me the story meta
give me the story element
so now we've got we was well basically
to target the buy
so
let's go down here we'll say story meta
and because we said we wanted to target
a span we'll say store it by
give it a span uh probably going to date
a test id on these as well so the test
id equals story by
and then i say story
meta element
because that's what we used and again
well not again but as i mentioned
earlier we can pass in prop so so give
this a color of
black
and that's good enough for me and we'll
just say bye
and then we'll say story dot bye
that looks nice that does look nice and
you know what just for
the sake of
brevity i guess in this particular point
so we've got story meta let's copy this
we'll say story
time
story time
and we'll set instead of time we'll set
posted so
we'll come to fixing that later down the
line as to how we can get some nice
dates to say okay this got posted you
know two two hours ago or 20 minutes ago
whatever it may be
and then we'll say story.time so if
there's a time
then say map time and i know there's
always going to be a time
but on that first render of react
because it'll render and say the stories
aren't there just yet or there's no
story in that component because it's
going to run through this even though
it's going to check for the url so we
should get that so we should just be
able to call map time which will allow
us in the future to give it that nice
url but if you don't me meta get it here
with the
story most likely
you're going to get some errors in here
because it's going to be trying to
access properties at certain op
positions in objects that don't exist or
if you're calling functions like here
and there's no
a quality check before it's going to
call that function pass something in and
maybe that function blows up down the
line so just just be aware of that um
going going forward
so let's see what we've got here
that looks good nice and clean after sir
um i don't know what people's thoughts
are on new lines for stuff like this
i sometimes do like to split up i don't
know
how much i should split up by
i mean that does look quite nice but
also does that i think i'll keep it
like that for now
so anyways
let's go ahead and take a look what's
going on do we have any nice stories
oh somewhat somewhat it's not too bad
it's not too bad
i'll um i'll take that i'll take that
for now so it looks like now because the
stories are going all across the page
we're gonna have to create something
that's gonna allow us to lock in that
story container
so let's take a look at the story
container i did think i added a space
there but uh let's take a look i thought
i added one here uh clearly not
let's see
um
let's i i thought you could use a
template literal so let's just uh
um
let's see let me get rid of this
um
one thing you could do here i guess is
i guess we could push out that we could
use a margin but
let me
use this particular method to give it a
bit of space in there
hmm
let's see
i suspect is there i was looking at the
posted one so we need to go back
actually
um
put that back story.time we're going to
the time
so we have a class name on there do we
am i even tagging story.time because if
if not i could probably get rid of
that um
we don't need that class name right now
story.buy because we're using star
components we can actually just target
the semantic elements instead so let's
just get rid of that too
um although i guess in here so we've got
we've got two spans story by story time
um let's take a look at the first one so
the buy we're going to be expecting
we're going to be expecting that it
comes in and yeah so so that looks good
to me we've got the italics
let's take a look here see i was quite
slow and jerking a bit because it's
loading 500 stories in the ui struggling
so we're going to take a look at how we
can fix that within an infinite scroll
it's not a good user experience right
now
so yeah so we've got this one on italic
so
i believe they're both on italic though
so let's have a look so if we're going
to story styles
yes uh which is we're gonna say spam not
the first type
let's say spam
first child
so margin right 10 px
let's just see if we can get a bit of
space in between that
i guess one thing we could do is put
like a bullet in between there or just
something to split that up
let's have a look did that not
so we're saying we're we're in story
meta which is
here this says span
oops
spun first child so we want to target
this one here
so span oh we don't need that
um
let's uh spam first child
there we are we've got some nice and
some nice padding on there so let's
let's go ahead and take a look now at
styles and what we want to do in styles
now is uh i kind of want to lock this
container
um
so story
stories container styles
maybe we can come up with a better name
for that down the line so let's import
styles
and then we're going to be importing
create global style
from style components
reason we want to do that is because i
want to insert something into the body
so we need to use create global style so
if i do export const global
style
i'll say create global style
and i'm just gonna for
brevity sick post in my default config
for most websites which is just this so
just to reset the box size in setting
the margin setting a color
and then
i guess what we want at this point uh
for global styles i think that's pretty
much it but we can inject that component
now
but um in terms of locking the container
we've gotta say stories container
wrapper style dot min
down here remove that
and then we'll say max width 1140
padding
top and bottom 20 left and right 15
then margin auto sort of go in the
middle
and that's our
stories container styles done
so we can import that now so let's go up
here
and what we're going to do here is
because it's our container we want to
input what we just got there was
um
so story style storage container
it's fine story container style so we
want
global style
and story container wrapper
so grab that
and we'll just pass them in there like
sir and we'll say from styles and then
story container
styles
perfect and what we can do here now we
can just dump in this as a component so
global styles
and then also we want the wrapper so we
can just uh
give that a date of test id to make sure
the wrapper comes in so we'll said do we
get a story's container when we're going
to test this
if so brilliant
uh let's have a look i'll just see if
we've got a nice
there we are it's in the middle it's
loading it's going to you know making
those
huge amounts of api calls so i hope um
the hacking news api doesn't like shut
me off at some point or after this video
there'll be a lot of requests i imagine
to api
uh so let's just uh did we have the
title
uh the title looks fine right now so
that's good
yeah packing news there we are
personally and brilliant so yeah we've
done well that's that's pretty much our
styles at this point so their style
components covered as you can see it's
quite jerky
um
and if you did you know run this in
reacts the components you've got a bunch
of stuff going on in here with different
keys
and if you you know run the uh profiler
you can see it's going to take a little
bit of time
let's see
stop profiling cause it's probably going
crazy at this point
and you can see we've got 7.7
milliseconds that's most likely star
components taking up that particular
particular performance hit there
so story.key 9.2 milliseconds uh 0.9
33.1 so you can see all these components
being rendered here and i only managed
to get 308
uh
let's have a look rank chart so this
context.consumer
i imagine that's a style component
what's um
doing its magic
so i'm not too sold on style components
at the minute if someone can uh you know
give me a good reason to use them
the only thing that i
well one of the things that i'm i'm not
too sure about is calling them as
components because
i imagine you could get a lot of
components just laying around that
styles unless you do what i've done here
where you just have a wrapper and then
target say the h1 selecting story
you know i'm targeting the air tag here
for the link i'm targeting the spans
it could get quite crazy so um yeah i
mean if there's a css expert help there
or style components expert feel free to
jump in the comments and let me know and
you know
find me on twitter which is in the
description let's have a conversation
and
i want to be sold on style components
um
anyways so we've got all our styles
we've got a fairly good looking api at
this point one api application that
calls an api with two different routes
so we're calling stories id and then
we're calling
we're requesting for a story by that
particular id
so if we just recap where we're at
we've got a container that houses the
story ids
and then when the story ids come in and
they've rendered to the page we call the
story component by using the map and the
map's going to go over about 500 times
if that's what comes through but we do
mitigate out some um story ids that uh
actually we don't mean to get out any
story id so we get 500 stories being
called
um what we do do what we do do what we
do
happen to
go ahead and do is um
we
when a component mounts we you know set
the story and the story doesn't happen
to be in there we just return null um
which i find is fa you know more than
adequate
um
but yeah if there's if you do feel
there's a there's a better way to do
this but i mean the hacking news api
isn't great in the sense that you're
getting 500 requests coming back
be nice to um you know be able to put
page pagination in there so i'll be like
give me the you know the first 20 i'll
give me this next 20. but we're going to
look at building that in ourselves to
help the
performance of the application so we
will be looking at stuff like infinite
scroll very soon one thing i wanted to
do is um
create this mapper so we was in uh we
were in
story.js and i said down here we want to
map the time so instead of giving us
this like unique time stamp we wanted to
say like two minutes ago or five minutes
ago you know yesterday two hours ago
whatever it may be
um and you can find these online these
i've called it a mapper um but you know
there's different names for it
essentially all it is is i'm just gonna
say it's a function that passes in the
timestamp and then it will return me
different scenarios based on
you know different intervals that are
going on so if we set seconds and we'll
say math.floor
um and don't get too hooked up on this
sort of stuff
uh this is a function i've had laying
around for a long time and used it uh
many times but it's not react
specific saucer
um
and that day it needs to be called with
uh some promise
uh we'll say let interval
math.floor
um
and then there's a bunch a bunch of
different um
you know divisions and additions going
on in here so
instead of uh borrowing you into with
this uh this maths that's going on i'm
just gonna
paste that in there from one of my
snippets over my keyboard
which just basically goes ahead and
figure out you know is it years ago is
it months ago days ago how's it go
it's not specific to react so i don't
really want to be teaching this it's
just
a map function that gives you some nice
stats so if we just put that in here so
we'll say map time
map time so it's going to run that
function over that story
dot time which is good so set input
and we'll say map time from
mappers
map time
and it'll give us a nice dare so let's
have a look
and again i'm hit there two minutes ago
three minutes ago whatever it may be
but
what's quite crazy here is it's hitting
that api you know all the time so it's
hitting that 500 times so we have to
slow that down
um but yeah let's take a look uh where
we at now we do need a space actually i
just spied here so uh where it says
posted so where's posted live
so it lives in story okay so posted is
down yeah there is um
so yeah let's just give it um an empty
template string see if that will fix it
there we are that does it nice um but
yeah okay so we've got the story uh
component so it's a nice little learning
project this you've got
one component that goes off and calls an
api you've got a container that goes off
and calls an api that is it it is a
component but don't don't get this mixed
up with saying oh this is a container it
is just a wrapper so that's my words
this is not react specific it's me just
saying this is a component container
that wraps a bunch of stories
so um i mean
let's have a look here what we've got
going on we've got styles we've got
services so containers mappers selectors
services it's just all made up words um
just like component but um these are
more what i like to work with so like
you know you've got your mappers you've
got selectors
actually in this case uh seen as a
a util i guess a util could be
put in as a selector so we'll move that
and hopefully vs codes
smart enough to
figure that out here it is look it's
found it it's giving me this and it said
it said select field is now a selector
can you save this for me sure i'll save
that um and it should still work perfect
that's brilliant okay
okay so now i think it's time
that we
maybe started doing the infinite scroll
so let's have a look so as you can see
we've got a bunch of
stories here and it takes a little bit
of time to load
because it's requesting 500 and that
will be hitting the micro task queue
so if we go ahead now and say we've got
constants we've got any components
right now what we need to create and i
don't want you to get too hooked up on
this
but we're going to create a hook
called
use
in
bennett
infinite scroll
dot js
and with the infinite scroll we're just
going to do the standard stuff
input react
then we're going to go ahead and say
actually we don't need react for this
we just need a few methods from yeah so
you you stir use effect
that looks good
and come down here we need some
constants now so in our constants file
let's go ahead and just set index.js
and essentially all we need in here is
two constants export cons max stories
and we're gonna get we know we're gonna
get 500 so let's just put 500 in there
and then story increment
is equal to
and if we go back into the infinite
scroll
what we want to do we want to import
story increments
max stories
from constants
and then i'm going to come down here
export const use infinite scroll
this doesn't have to be hook but
i'm in the mode of creating hooks at the
moment so uh i thought i'd
show you how to do these and since this
is a tutorial
i may as well take the opportunity to
show you how to use custom hooks
so we're going to say loading set
loading equal false we're going to
initialize the state with false
and then we're going to do another use
state so
use step
we'll say count and then set counts and
then use the story
increment so we're going to say the
count starts at 30 so
say if we do something javascript like
uh
you know if we use slice
slice from 0 to 30 when the user scrolls
got from 30 to 60 and you oh we could
say go to zero or 60
because we want to display all the
stories we don't want to get rid of the
ones the other ones so we could just
keep doing this until we hit 500.
so what we want to do now is
we want to do something create a method
essentially
so
what ultimately what we're going to do
here is just say handle scroll
and then we're going to say
uh we need to get the window so if i
just log out window here
should be able to access the window
directly and react
so look
go into our console in dev tools
we have to import this actually so if we
go into
it should be let me get rid of that
don't need that don't need that do not
need that
we don't go into stories container
then we do
imp
we should say
um use infinite scroll from hooks
use infinite scroll
and then if we
um let's see if we just go ahead and
let's have a look where i the structure
i'll count because we're going to return
we've got a return count but it's not
there at the moment so let's just say
um test and we'll call that method
it's never defined okay
we'll call handle scroll
i just want to see what i want to show
you what window returns here
here we are access to the window
so there's a bunch of stuff on here
um
that we can access but i don't want to
confuse you too much as to
you know what's what all this stuff is
we could leave that for another tutorial
but you've got stuff like local storage
um
animations the navigator uh let's have a
look on key down all these dom
based actions
the origin
the outer height the outer width
but more specifically what we're looking
for
you have
inner height should be in here somewhere
in a height
and then we'll say well that's what
we're looking for now
and then um myself have a look what's in
document
so even though we've got the inner
height what we want to
log out
we should be able to look for
document element
and then within document element there
should be
scroll top somewhere
there we are
and if you used to reload that window
they should update but what we want to
do we want to do a calculation and say
okay
in a height
plus the
um scroll top
is not equal to the offset
so let's have a look for the offset
should be
in here let's have a look
there we are offset height so we want to
make sure it's not bigger than that and
right now i can see it's pretty crazy
um if if it's uh
say if it is bigger than that then we're
going to set attributes to say if it's
loading or if it's not loading and then
also we don't want to be hitting
a refresh with react all the time so
something we can do is put a concept on
this function called a d bounce
to make sure if i scroll i can't just
keep scrolling and scrolling and
scrolling when i do hit a scroll
it locks my scroller for 500
milliseconds or a thousand milliseconds
whatever it may be just to make the
experience a bit better
so let's take a look now i'll just go
back in here
we can uh delete that delete that
um i'll just delete that for a second
what we're going to do in here we're
going to you know do that conditional
check in here to make sure that we can
calculate the height correctly
and then we can do certain conditions
based around the height
but please do not get too hung up on
this this is
basically just checking if you've
scrolled and then what we're going to do
we're going to do some react type stuff
right okay
as mentioned don't get hung up on this
but i should say okay if window
dot inner
height
plus
document.document element
dot scroll
top
is not equal
to
the document.document element
dot off set height
or if it's loading
if that condition happens to be
true for example
uh
well depending on that condition comes
back ours we can just return false
and then else
set loading
true
and now
save that cool that's good
of pulling use effect
and what we're going to do we use
effects we're going to have two of these
in here two listeners so if it's not
loading
just return out of here
because we don't want to be going ahead
and doing all the set loading unlocking
the count we'll say if count plus story
increments
is greater than or equal to max stories
then set count
max
stories and what that's saying is
basically
if we have a count of 480
plus the story increment which is 30
that equals 510
and we don't want to
get let the users keep scrolling because
we've already exceeded the max stories
right so we're just going to set the
count to 500 and you know quit the
scrolling there
else if they if they are below 500
stories let's just say count so we could
start off with 30 they scroll
once on the page we're going to add
store increment which is
30 so you'd have initial count plus
another
then it hit 60 and if the user scrolls
again because the count's changed
we'd hit 90.
and we do that till we get to 500
stories
and whilst that's all going on just say
set loading false so that we can
continue on and we're going to keep a
watch with our use effect on loading
and we're going to do one more use
effects
and i'm doing two separate use effects
because i don't want to be watching
actually you know what i don't care
about counting there so let me get rid
of disable that and i should just add
the exhaustive dependencies i want
another use effect because i don't want
to do anything in here i just want it to
run just at once so we're going to do
the component did mount this is
re-watching loading all the time
for a change value this one is just
going to do it once so i'm going to say
window.add event listener
and i want
it to listen for the scroll and then
handle the scroll
let's just do this and one important
aspect here is we have to sort of
unsubscribe from this event listener and
the way to do this to do a clean up in
our use effect and react is return a
function that does window dot remove
event
listener and we'll say remove the scroll
and then
remove that method too
and that's saying okay we're going to
add the event listener
and then once this use effects done go
ahead and just remove this listener
because we don't want these to be
hanging around and creating multiple
listeners or whatever it may be we just
want to do a quick cleanup in here
and after all of this we're just going
to say return
count
so we should be able to use this now uh
it should be in a workable state but
there's still some stuff that has to be
done to it so i should be able to grab
this and say
const accounts
equals use infinite scroll
and what we want to do down here even
though we've done the map what we want
to do now is we want to set dot slice
we'll start at zero
and then go with the count so for
example
if the count
so user comes on the page it's going to
be 0
and 30. user scrolls is going to be 0 60
user scrolls again 090 user scrolls
again 120 and so on
and that's what's going to happen but
then you're probably saying to me now
but it's going to re-render
a bunch of these components out already
on the page it's going to re-render them
for no particular reason like that's bad
right yeah we don't want to be
re-rendering these stories all the time
so there's a perfect solution in react
for this
and what we're going to do we're going
to pull that in from up here and it's
called use memo
i don't want to implement this right
away actually it's called memo what am i
talking about i don't want to use this
right away because i want to show you
why this is very important so let's save
all this let's have a look see if we've
got a working
page so you see the scroll bars better
and it seems to
be broken
so what's going on
so it doesn't seem to be scrolling maybe
there's something wrong in my user
use infinite scroll
uh hook
so what we got here we got the loading
let's debug this together
she's gonna be doing a lot of debugging
um
go say count that's right we're gonna
handle the story so we're gonna say
window plus document element is not
equal
to the offset height
or loading return false that was good to
me
and we're going to say set loading
and what we're missing here we've got
another use effect that's saying if it's
not loading return if count plus story
increment is greater than
set count set count
plus star increment
max star is set loading false we're
watching for loading we have a
use effect that adds an event listener
of scroll i'm going to say use this
method for a handle scroll so when
so when we're listening and this happens
we're going to uh
call that function
and we're going to do return window dot
event listener scroll handle scroll
so
i think i've spotted the bug but i just
want to uh
go ahead and
keep debugging this a bit more just so
we can get in the uh
because it's never smooth sailing right
we we do want to uh
keep track of what's going on
um
let's see
counts 30
counts now 60
and that's all it does it only goes to
60.
very strange
does it go any further
it only does one scroll and i'm guessing
so i've pulled in news
so we don't have to watch the count
because what what's going to happen is
um
it should refresh each time so even
though we've got those stories
on scroll it's going to fire back
as if the count has changed
so this count will just update here
use
effect okay
so let's take a quick look once more in
here the
use infinite scroll return seems fine
for picking up the event listener we're
watching the loading
um
i i'm gonna take a guess
that this is not working simply because
either it's something to do with our
d-bounce
or
it's something to do with a scott story
container so as you see
it knows counts updated
so like count in here so for example
where it says count here so if it's not
loading go ahead if count plus
star increment is greater than or not
set story
set false loading should be up here
um
so yeah it does look okay i don't know
if anyone spotted this just yet
um i think i know what it is
um so i think i know what this issue is
it comes down to and this is one i'd
actually like to leave with you guys if
you want to do some work on this after
if you've zoomed in
the offset seems to be wrong
if i zoom out
i can hit the count
ignore this message at the minute we'll
use a clean up properly
you see all the counts updating
60
90
120
150 we should be able to get to 500
that'll stop us
the count should hit 500.
we see i can just keep scrolling and
then it kind of stops and it requests
whilst it's requesting
420 and it's a bit jerky it's not the
best experience that's why we're going
to implement a d bounce
500
and and that's it what let me scroll
anymore perfect
um so yeah let's have a look now
implementing we don't need counting
there anymore we don't need it there
because we're not going to be watching
count count should just update here so
when this story container
goes ahead and does its work and gets to
500
it'll look through here and it'll say
okay well infinite scroll has changed
this in here has changed so
if we're watching
count
we're actually watching counting here
but if loading is being changed that
means count the counts changed
so if loading does change which is in
this year's effect here
then what we're going to do go change
the count
and we can update the count here
so let's take a look so what we can do
actually you know what i'm just going to
put the count
uh let me
let me put it back in here a second i'm
just going to leave it there so i can
debug you can actually put it in there
um
yeah so what we need now okay that's
good
what we need now is a d-bouncer open up
your explorer
and it should be utilities folder in
here
so
let's have a look we're gonna drop in
here something called the bounce.js
and this is another thing i don't want
you to get hung up on but let's create a
function called d-bounce and it's going
to take a function
it's going to take away it
it's going to take an immediate
and then it's going to take an args
and it may be a bit confusing i was just
thinking about this that why is this
updating
like why is this stories content
updating and getting a new count each
time
well i'll show you in the profiler
um
in the dev tools as to why this gets
updated so you can see it visually
because there's nothing in here if i got
rid of counter sir
well you need to run this use effect
apart from this infinite scroll
obviously but
this use effect here it's like well
nothing's in here so why should i update
this component well i'll show you
shortly it's better to visually see it
as opposed to me explaining it
let's just do let timeout will return a
cleanup function
that says const
contact this
cons call now
immediate
and there's no timeout
constellator
time out equals null
i know i've mentioned it plenty of times
but
i'm you know i'm trying to teach as much
react as possible here um
so i don't really want to get hung up on
just an infinite scroll
um if you are interested feel free to
drop some comments and we can talk more
about this
um or you can find me on twitter at carl
hadwin
i should set a timeout so i say later
where
and then if call now
function dot apply context args
and that should be
okay
oh
set timeout
that should be all right so let's close
up and the way to apply that function is
well what we want to do we want to apply
in our use infinite scroll
wherever that's gone
um
so we want to apply it when apply it
here so
when handle
scroll gets called
we want to wrap it in
um a d bounce so we're going to say
i need to import actually
import d bounds from
utils d bounce
and we want to wrap the entire function
so if that
this bit here actually this bit this bit
all of them is yeah it's this bit so we
want to wrap this handle scroll in d
bounce and then
we're going to do the d-bound see what's
going on in here and then you know if we
get get the you know the green light go
ahead do the handle scroll if not you
know wait 100 milliseconds let's put
this 500
and uh yeah basically that's it for use
infinite scroll
and uh it should just work now we've got
the infinite scroll it should give us a
nice d bounce sort of look
there is it's locked to the
scroller for 500 milliseconds
and feel free to put that to whatever
you like whatever you feel is the better
user experience
um
so we have select fields we have a bunch
of stuff going on here i don't know if
it's at this point because we have a
functional app at this point maybe it's
uh
do we have fixtures in here no i don't
uh maybe it's worth let me create a
folder close all these folders down
i'm just going to create a fixtures
folder and the reason we're creating the
fixtures folder is because we're going
to start preparing for
tests or testing
so if we just go ahead and in our
fixtures well we can just create an
index.js
index.js and what this does let's just
create a singular story so do export
const
singular stories because we don't want
to be hitting the hacking news api all
the time especially when we're running
tests right
um
so let's just say ids one
time i'll let me grab a unix timestamp
um yeah we don't be hitting this all the
time so the reason for that is we're
just going to run the test against this
tarnish google responds this is one of
the articles i saw url uh something
uh something calm
new hacking news
tut
um yeah we're gonna be running the test
against the live site
um so it's just uh export cons story ids
and you could go ahead and check out the
uh
you know the infinite scroll but uh
i don't feel it's necessary if we can
manually test it
and um
just say an empty story would be all
this it was just so undefined
so id
time
[Music]
title
url
grab these boom
[Music]
that looks good so we've got a fixture
that we're going to import into our
tests so do we have a testing folder we
do not actually
create a new folder
underscore underscore tests
uh firstly what we're going to do
um
[Music]
actually you know what there's a there's
quite a few things to test here so
what i actually want to test
we're going to test the application like
kind of end-to-end ish the hacking news
api so i can use
service which is this
we're going to test the story container
storage container and then we're going
to test the component which is stories
itself
so let's take a look at that and then
we'll do a few tests just to get some
confidence in our application it is
obviously working but um
there is a few things that we can test
and you know to get confidence whether
it be this is going through a
shared code based or
it's going through a pipeline we want it
to be passing tests
um so yeah let's take a look at that uh
and we'll jump in we're going to write
probably three or four tests we're going
to be using react testing library
um and there's all sorts of nice stuff
you can do here right so i've left you a
project i'm going to leave your project
after the test is done i can go ahead
and pull in different apis you can test
it differently you can remove the
infinite scroll you can modify the
infinite scroll
and then once all this once this video
is
a released
or two from now you'll see the second
video which will be the graphql
implementation hooked up to this and
this will go from hacker news
application to a news reader the news
reader will read multiple apis and then
we'll modify and adapt certain data that
can be returned to our front end
so what we're going to do here i'm going
to just modify the screen a little
hopefully everybody can see this i'm
just going to
throw my terminal in here
and i'm going to close that just so you
guys and girls can see what's going on
um
close that close that
and what we're gonna do
this i don't i'm trying to think which
test might be easy to break in first so
we've got the story the stone storage
container you know what let's jump right
in head first let's go ahead
do tests
app.spec.js
and what we're going to do in here
import react
oops
input react
and we need to import act and act
now um
react dom
test utils
actually i will explain act right now
let me let me do in a second it's
basically asynchronous
rendering so instead of
well yeah okay let me explain in a
second you'll see you'll see it better
we need to input all this stuff that
we're using because we do want to mock
this out and when i'm saying mocking
it's like giving it some sort of fake
response
because we don't either we don't need to
test this particular bit uh that well
or we just want some empty components
because we're not focusing on testing
and testing them
always simply like if it's axios we
don't want to be hitting an api right
so um
there we are that looks good and we need
to bring in the infinite scroll uh use
infinite scroll
from
hooks
use infinite scroll
and let's have a look story increment we
can bring that into i guess
increment
uh that was in constants wasn't it
that was good okay we're gonna say this
is react testing library right here so i
said before each can i make that bit
just a tad smaller
um
that seems okay for now
i'll just uh pull it over there for now
and we'll keep running these tests we'll
go set before each this is before each
test
do a cleanup and by saying that it's
cleaning up the dom
which for me oh actually you know what
one crucial thing i missed i forgot to
import the
testing library
uh clean up generally i'll do a render
and clean up i'll pull those in and
maybe you know sometimes i might pull in
uh what else do i normally pull in maybe
uh
fire
click event fire event i think it is
um do we have this actually
oh i don't think we have it so what's
let me have a look package
ah we don't have it okay we need to
install this so uh if you go ahead and
uh dev dependencies
dev the
i can just
dev dependencies
i'm going to say testing
library
reacts
now i said give me
9
uh what's this saying here
call unexpected um call unexpected where
really
let's close that down
oh what's this doing here spinner
anyways
let's go to package.json
like it did with mine there
um it's still going but um let's just
continue on writing this in this
app.spec file it's probably easier just
to generally fire in um do a yarn ad
react testing libra
so let's go ahead and say
describe
and we'll create a describe function
that's going to give us we're just going
to say up
and to be honest you don't even have to
do a describe because not much is going
on sir i'm not going to do a describe
i'm just going to set it
one thing before we do the 8 let's just
do a yarn install because we need the
testing library as you can see we've got
the the red
squiggly lines telling us basically it's
unable to resolve
so once that's installed we should get
the testing library library which will
be nice and i was just thinking
briefly then instead of using it
i generally use it
as a function to test stuff when it's
inside a described block if it's outside
the describe block we can just do test
which uh makes a bit more sense let's
say it renders the application
it has to be asynchronous because we're
doing asynchronous calls
and we're going to get the use infinite
scroll uh to find never used okay that's
fine uh use infinite scroll dot mock
implementation
and then what we're going to do we're
going to say count let's go say return
the implementation of you use infinite
scroll return me count with 30 and
that's all i care about at this point
and that's all i ever want from used
infinite scroll so i don't want to bring
in the actual implementation i just want
you to return me an object that says
count is equal to 30
and then we're gonna have to mock the
get story
so we're gonna do mock implementation
again
um i'm gonna say promise dot resolve
because on that get story remember
because it's asynchronous it's always
gonna return us a promise so we have to
resolve something and that's why we had
the fixture file
fixture in here and i'm just gonna say
uh for this get started return me this
singular object with this stuff in here
so i'm gonna say resolve me this i don't
want to hit the api's want you to return
me this
and that's the power of a mock so get
story ids dot mock implementation
i'm gonna say promise dot resolve
story ids
likewise for the story ids um i don't
care about the implementation of get
story ids you know hitting actually i'm
just gonna say okay
give me this function and
just return me a result that i'm
faking essentially and that result i'm
faking it with is story ids which is
this array here with one so i'm gonna
say if you get one go ahead and get a
single story
and this is where the
the real business comes in so set a
weight act async
and then we'll say arrow function
and this my friends
is
great basically what's happened um
recently is
you didn't used to be able to i don't
believe use an asynchronous act so you
couldn't
do some work say for example
go get me these stories because it's a
synchronous and render these
um
i essentially want because when this
test runs it's just going to run
immediately right and it's not going to
have say the story on the page so i want
it to
await this
so if we didn't await this and you get a
bunch of errors saying those
asynchronous tasks going on and your
renders all messed up
so we're going to use away act and we'll
take that off actually in a second
but i want to show you this get by text
query by test id
i'm going to say render me the
application
um
let's see then await i'm going to say
wait for the element and wait for
element in react testing libraries in
asynchronous utility that basically
allows me to pass it
one element or an array of elements to
say
once
the asynchronous tasks have happened
do this so it's going to say await this
this bit here
so just wait on a response from the
asynchronous task once it's resolved go
do this stuff so i'm going to say expect
get by
text hacker news stories
and you know what i want that to be
truth i want it to exist
and we'll do a comma because we're
passing an array here
and i'll just uh manipulate these query
by test id we want to make sure story
buys there because that story by is um
who the stories by
and we want to check in the uh
text content so we can check the text
content here
and uh since there's going to be a bunch
of story buys we can't use get by text
right
um well really what we can't do is say
you know
buy this person or buy this person get
my text only allows us to get one
particular element that's on the page if
there's multiple elements with the same
uh
with the same text it just what works so
what we're doing here is we've got a
query by the test id for story by and
story buys like a spam tag
um so we're just going to go into that
text content i believe it's a spam tag
calendar but we we made it i just want
to say bye
you know what i can't remember what we
made it buying a fixture i think it was
by me actually
yeah by me
um get rid of that i don't need that
that looks good um hacking new stories
yep that's the title and what we also
want to do when i make sure this is in
here so i want to make sure the title is
in here
and this will all start making sense you
can see these squiggly lines here saying
look it's not imported from
react testing library
so yeah that all makes sense so let's go
ahead and just say yarn
test
let's see what happens
and i'll pull up the coverage if i can
on this actually
mock implementation is not a function
okay great
uh so it's saying here we're saying use
effect from the hooks
um oh what we've got to do actually we
have to create our initial mock so we're
going to say just oops just.mock
dash dash hooks
use infinite scroll that'll give us an
initial mock so we can start modifying
that mock specifically
likewise with
our services so
i can use api
you know as soon as it loads in
get me the story
jess.function and by returning a gesture
function it allows us just to you know
make assertions on that function did it
get called did it get called with this
data all this sort of good stuff so get
story ids
so that should now work except take a
look
we could rerun that test automatically
but it kind of uh nukes my system
perfect so we've got account in here
but what happens uh i'm hoping we can
demonstrate i don't know if it's
possible to demonstrate this async act
we may actually not need it with the um
wait for element
hopefully yeah we'd actually need it but
that's how you do use async access come
out in i think react 16.9
uh we don't need it there but we may
need it down the line so we'll keep it
in the tool bag for now but let me just
get rid of these
and save that let's see what happens
here we are look unexpected talk and
that's basically syntax error so rerun
that
unable to find an element with this sort
of stuff great and why is that well the
page the test ran but there's no content
so we have to await that data so we can
do that by just saying
putting this back to a wait for element
and we also have an asynchronous test
here which is great so if we run that
test once more
save that it's gonna probably failed i
think i caught it in time to serve
yo i did that's great
uh we can check out count because counts
basically
uh story container
don't need that there either
let's take a look
that looks good to me so basically
that's how we uh mock out well not knock
out but that's how we test the app.spec
so i'll pull up the um coverage now and
then we can have a look where stuff
maybe we haven't hit or stuff we do need
to hit
all right yeah sometimes um when i run
the test it don't give me coverage and
uh you can set this up in your
package.json but i wanted to give me
coverage for everything not just
specific files so even though it's only
one one test i'll still want coverage um
and it not to get cached so let's have a
look at app.spec.js running coverage
perfect
we've got coverage if i go back here
open up uh let's have a look
coverage
where is it
let's see
ah okay
go into your
package.json
and what we want to do we have to
[Music]
have a look for coverage reporters
coverage fresh show is there a refresher
oh there's nothing in here
okay
we can do just and we've done this
before in some in uh like the to do with
tutorial so collects
uh actually i'm not gonna collect
coverage for a minute i'm not gonna i'm
just gonna get it from everything but so
coverage
threshold and this is a good standard to
get a good mindset to get yourself in
always have a good threshold so branches
95
um
functions
lines
statements
that looks good
uh coverage threshold
this is whinging out
462
um
let's have a look
unexpected talking about oh
one
two
[Music]
all right that seems fine we'll we'll
see in a second
um
so we've got coverage if i spell that
right threshold
we have global
of the global coverage and the reason
we're not getting any coverage report is
go away
um
when to say
coverage reporters
give it an array of html and text
and what that's going to do
should give me a
oh yeah i didn't like that
uh coverage threshold i'm pretty sure
collect coverage from coverage threshold
yeah i can't spell threshold so that's
that should work now
should give me a coverage report
let's have a look
there we are index.html
perfect we've got a lot going on here so
we might have to clear some stuff out
that
we don't exactly want to be testing so
we've actually tested our story by just
doing an app file but i think what's
best is if we test it individually as a
unit test
um even though we did kind of test it
and you know you do get this fall over
between app and sorry container because
it's kind of doing the same thing but um
do as much coverage as possible just
test everything you possibly can
if it's unnecessary to test uh you know
you don't have to do it but
let's have a look let's go ahead next
and create because this one's gonna be
quite similar to start up
so we could just use this as a base i
imagine uh close that down
um
so let's pull in this as a base i i
don't i think we could it's the exact
same test i don't even know if i have to
test this honestly
uh
[Music]
yeah so we're gonna be hitting the story
container
it's gonna be doing exactly the same
stuff like if you just replace story
container here
with up
i mean i can leave it in here if you
wish containers
uh
is it did i call it containers i can't
even remember containers
sorry content
come on
uh story concerner stories container and
you know what you'll probably get
that will most likely run completely
fine and you it you know you can modify
stuff in a storage container
um
there you are look perfect but i mean
maybe you could just mock that in the
app
and then you know just say okay it
renders
it just renders that's all you wanted to
do as opposed to doing all this
but anyways i'll leave that in there let
me see i'm going to put this on github
so
any modifications on the test
let me know because i'd like to see that
story.spec.js is next clear that out
um this one's going to be you know it's
going to be fairly similar maybe you
want to put some stuff in your test with
it the api fails but
i'm not gonna go crazy with the testing
i'm not i am kind of a purist but in the
same hand uh on the other hand i'm not
i'd like someone who's really good with
tests to come and buff these up if
possible
um but when i start testing i'm like
okay
i've already tested this stuff i've got
similar components being used throughout
so i may as well
you know just
copy this to be you know i may as well
copy it i know story ids isn't being
rendered in here the infinite scroll is
not going to get rendered we don't need
the constant
uh infinite scroll that can go we're not
doing the story ids because we're just
looking at the get
story uh renders even though that's his
application renders
uh let's change that to story component
with content
uh so what did we have here story so
that one goes to renders the story
container with a story
uh so yeah let's see here so um we're
going to say okay we're going to mock
out this implementation with a single
story
we are gonna
render a story and we're gonna give a
story idea of one
components
story story ids don't need that
get story ids do not need that
infinite scroll do not need
uh so yeah get story do we need a clean
up yeah we need to clean up but um
seeing as though
there's gonna be multiple mocks in here
one nice trick you can do
put this down here
is we'll call that function like that
and then we'll say just dot reset all
mocks and that will reset on each test
so this sort of stuff or this mock
implementation here
will fall into the next test
um so we get a clean test so we're going
to clean the dome and we're also going
to clean all the mocks
and i think uh even this is asynchronous
yes it is i'm going to mock the
implementation of a single story we're
going to
render out a story pass it a story idea
of one
because that's in our fixture
then we're going to wait for element and
we're going to say i can use
let's just actually let's say also
um i know that we have a test id in
there of i think it was story or story
always check your components there
should be a test id in here yeah test id
story which is there
so if i um i i basically just want to
call query by
uh you can use get by test id query by
test id
um
hmm
let me just say actually we could do
query by test id and i'll i'll explain
the difference in a second
um let's say query by test id story
let's see what happens
um
get by test
text
then we'll say
[Music]
the hacking news stories isn't going to
be there because that's not in the
container tarnish will be there text
content
all right let's have a look where we're
at with this sir
yarn test
let's test everything
we can run individual tests as well i'll
show you how to do that in a second
works fine perfect um
so component story that's done even
though it's covered in another two tests
but to run individual tests just do yarn
test
give it the
relative path
and just run that
you can also run individual coverage on
that too so if i quit out of there
and say yarn test coverage it'll give me
the individual coverage for that as
opposed to running all the test coverage
um yeah so that was good to me
so um
let's take a look here so we've got get
by text query by test id
um
so let's expect query by test id story
uh to be truthful
you see it's all checking perfect so if
you switch that out now to um
i think it was get
by
get by test id
let's see
both work the same um one of them i
believe so yeah so what we're looking at
here okay we want to see what the
difference between get by test id and
query by test id is
and essentially what happens is so you
could use get by test id
if that happens to be false so you could
just actually call this
like that and if it happens to be false
it'll throw an error
um
if this here query by test id
happens to be
you know false it'll just return null
um i'm not too sure which one i like
most i i would like to get an error
um but you could just do two truthfully
but in this case i'll leave them in so
you can just see
how that works so let's have a look
so get by test id
let's just rerun that and it's not going
to be there
hopefully we get a nice error
taking its time there we are
just give me an error
unable to find but if i run query by
test id on that
it should also fail
because i've got to be truthful
but you see how it doesn't give me the
debugging as well
um but if you used to do this so for
example
you just called it here so let's keep an
eye on this
come on
there you are i couldn't find it so what
happens if i do a query by test id
should hopefully get null back
oh it doesn't doesn't return anything
which is quite bad
so
in this case
i i'd probably stick with
get by test id honestly i think it's a
bit safer
so we don't actually need that
get rid of that
perfect that looks good to me let's
check out the let's check out the
coverage
there we are
um what was that on that was on
story.spec
yeah it's already covered from the kind
of an integration between the app and
the story container
so a nice one that we're going to be
doing now
is the hn api.js i can use api that's
all it is uh you can stop running those
tests now and there's there's no real
need
um so this one we're going to import
we're going to mock axios because we
don't actually use the rail
implementation
we're going to say
from axios and you don't need the named
input because axios is a default so
let's just say input
get me the story ids get story
new stories url story url and this test
is
is really nice actually i like this one
and
it's not this one specifically but
i like testing apis because you can see
or did it get called with this data did
it not so let's import singular story we
need our fixtures
empty singular story
from
fixtures
all right
oh yeah that looks right
uh how many tests we've got going in
here now so what did i do with this when
i did test it out just the one so yeah
we don't really need a describe here i
mean
actually you know what we could do with
a describe here because we're testing
this and this so
firstly let's uh
let's do a nested one
i can use api
forage and you can put your before each
by the way in the describe um
just dot
reset all mocks we need some clean up
and then we'll do
clean up
um did we not bring in react testing
library actually do we need a clean up
we don't really need to clean up because
we're not doing anything to the dom here
we're just basically testing the api
um
describe
uh let's say get story
um get story functionality i don't like
testing functionality but in this case
you know um
i'm breaking my own rule
for now let's just do one describe
so what does it do well it
requests and gets a story from the
hacker
hacker news
api
and then we can do axios.get because
that's a function on axios and we're
going to say mock that implementation
because i know that's what we've been
using because
we did
implement that right we we used to get
back way back over in
service
we'll use this get and i just want to
mock that out
so do promise.resolve
and i'm going to say
i want it to match exactly how it runs
through my data so i'm going to say data
and
spread a singular story in there
there we go that looks good to me
and then what we could do we could do
const entity equals aware get story and
pass it one
and because this we're using an aware we
need an asynchronous function
and what we can do now because this is
mocked and it's not actually going to go
call the hacking news api it's just
going to give me this
and that spread story what's happening
here with these three dots we've got
singular story um i'm creating a new
object
which you probably just could just well
you can just do
uh
should i just do that actually let's
test it we'll find out
dot resolve data which is a single story
we can test it let's see what happens um
so i said we want to expect
axios what
happened expect axios.get
to have been called
times one
then we're going to say
remove that
to have been called with and then this
is where the magic comes in
story url
plus one being
uh
this here get started
and then what we're going to do we're
going to say dot json because that's
what is actually going to be sending to
the hacking news api and saying give me
this story this num the story of an id
of one i'm going to say that expects
entity dot
so equal
and we should be able to put single
story in there
let's test this hypothesis and just see
so i'll get that yarn test
let's see what happens maybe it doesn't
like a singular story going in
it should not should do let's see
requests so don't like the mock
implementation and i can already hear
everyone screaming to me it's like you
told me to do this early you have to
mock the actual implementation the the
module
let's go ahead and do that
so we can actually you know used use our
mocks and we get the mock implementation
so soon perfect it passed
but reason we mock this is so we can do
stuff like mock implementation on that
so we know that axios is in there and we
say mock the implementation because
we've got a construct constructor ingest
that sets up all these nice functions
for us so like for example if you used
to run axios
we run this test
we should get a bunch of nice stuff out
here
you see so we get um
a bunch of mock implementations here so
we do get the actual axios uh
we'll get the access function and get
mock implementation clear all this good
stuff all because we did this
uh but then you also get stuff like here
headers uh inceptor response so you can
get the original functionality if you
wish to get the original functionality
um
but in this case we only care about the
dot get
so we can remove this axios
maybe i can show you it also in the mock
implementation of the story so if i
do get story
i think that'll return just a function
value actually
oops
grab that
let's see
there we are so we'll get the get
started because i've mocked it out
here
and i've just said give me the jest up
function but you see the difference in
here
is that's just going to give me the
default marks on everything whereas the
get story
if i mock out that particular function
it's going to give me all this
functionality here
and then you can run stuff like you know
mock implementation
like that which is what we're using
there
don't go ahead and do that
um so yeah hopefully that makes sense
i'm always open to answering more
questions i know these can watch in
these videos it can get quite tedious
and some stuff you may understand some
stuff you you may not understand but
essentially that's that's programming
you're going to understand some stuff
and you're not going to understand some
other stuff and
it may click one day it may not click
another day so always come back write
notes
ask people it's the best way to just
communicate people
so what i can do here will say
[Music]
it
[Music]
does not retrieve a story from the
hacker news api
but handles
gracefully
let's pull this over here
does not retrieve a story
from the i just say api
handles gracefully i'm going to be
rewriting a lot of this stuff when we do
hit the graphql bit
again we can just go in here copy this
and i don't i don't want it to uh where
we are i think
uh space
i don't really care about a single story
here i want an empty singular story
and we can mock an empty singular story
and we're going to say we want it to
equal when it returns a singular story
so let's have a look
perfect uh just need to go back into
story dot spec and remove that
console.log there so you're getting all
this stuff here
again this is all going to be on uh it's
all going to be on github feel free to
contribute to the project
graphql is coming so it's going to be a
news reader not specifically hacker news
we will be using the hacking news api
but we're going to be pulling other
stuff as well using graphql
get story functionality
doesn't retrieve so we've done the get
story so now all we've really got to do
let's have a look where are we with
these braces
describe
get story ids that's you know that's all
we've got left to do
and we can pretty much just go ahead
copy this because we've got similar
implementation so it makes our test nice
and easy
requests
and gets
uh let's change this to story ids
from the hacking news api
we will mock out the implementation of
the get once more
and the reason we're not mocking this
out up top is because we want to change
it on each test right and we're clearing
it on each test as well by doing
just.reset all mocks
so here we're just going to say give me
story ids which uh is in our fixture if
you forgot it's there in the rear with
one
um access dot get mock implementation
promise dot resolve return me an um an
object with a key of
data there's a property and that
property is an array with one inside so
we'll say get story ids we don't have to
pass anything to get story ids
and we can basically say how many times
it's been called once
we only only thing we really care about
here is uh does it hit the
new storage url
because that's what we plan on hitting
it with which is this a buildup of base
url which is that
new stories and it should go get me the
new stories and then we'll say we want
it to equal
story ideas
let's have a look what goes on here
certain stuff we worry about in our test
perfect even that's hitting the
the wrong test
uh yeah certain stuff we won't worry
about within the tests um
i'll try to stay away from
implementation but doing these sort of
tests gives you confidence in your api
so i quite like doing them
maybe it's just something i like doing
guest story functionality
um
let's put that to get story ids
you can see the names come inside here
from the describe and the test so
hacking news api gets story requests and
gets a story
there we are perfect
um
so i'm just going to go ahead now and
check the coverage report see where
we're actually at
um it'd be useful if i actually run the
coverage uh so let's have a look
there we are
the links are in the description by the
way for this particular project and
other projects i've done
all in the description i'm on twitter at
carl hadwin my github is
in also in the description of carl
hadwin
we don't care about hooks in this case
and we don't also care about utils i'm
not testing the d-bounce
service worker we don't care about that
so okay in this case
we're getting very close to the end now
stuff i don't care about i mean this is
very subjective but uh certain stuff
that i can manually test
i'm not gonna test honestly um if i can
just manually test it
get coverage
from
give it an array
even though the debunks don't work um
the infinite scroll kind of works but
when you put it on a different screen
um zoom it don't work too well so i
could fix that now or
if one of you want to fix it that would
be really nice
um not only would it save me the time
but uh
it would make this tutorial shorter and
also
if someone could write an implementation
so this is why well not implementation
but a few notes around
why it uh was like that you know that
would be nice but like i said people
i don't know people learning this i
don't want you to get hooked hooked up
on a d-ball so i don't want to get
hooked upon
all the other nonsense and the nuances
that may occur
um i just want you to learn react um i'm
not forcing you to react i'm just saying
these are some of the good stuff uh the
functionalities for hooks this is hooks
this is components this is containers
all this stuff that kind of brings it
together
um as a react developer
so it's all good stuff to look out for
all these are like fundamentals and
you'll use these day-to-day
so anyways i'm going to rerun the test
um
i'll show you what i'm running by the
way for this yarn test coverage watch
all
and hopefully we get 100 coverage once
you get rid of all this uh all this
nonsense here what we don't want to test
i'm not testing a service worker even
though you can turn the service worker
on
oh it's not met oh selectors is missing
um
by the way if you do want a service
worker i'm going to run this through
lighthouse very shortly
all perfect hundred percent uh selectors
should go in a second
uh source selectors uh selector selector
selectors
that looks fine to me let me rerun that
once more
come on
perfect
you'll see this one here is uh giving
you
a 50 in branches because we never hit
red but i wanted to show you our style
components work and giving you
um an opportunity to look at how props
work there too so you feel free to
change that if you wish
um
so yeah let's run this through
lighthouse
right now i think we i think we're done
we've got a working application we've
got it working pretty quickly but then
we just wanted to make sure we could uh
i you know oh one thing we didn't do we
didn't implement memo
so this is this is a really good thing
so can i just get rid of the um terminal
right now
uh
let me see here i'll just pull this out
stop snapping there is
go back to this
cool okay one thing that's really
important right now
story
container
yeah so one one of the important things
here is even the
react isn't going to re-render this
story because it's already there right
it's not going to hit that render
function
but it is going to call this story
um so we'll go in here it's not going to
just ignore it it's going to go in here
and be like okay well it's here
um let's remount the component and uh
maybe this is a quirky react i'm not too
sure actually but it's going to
re-render this component and you can see
here it's like okay um
if we log out the con this story id
would expect it to be in there once and
it should just be in there once
let's have a look it should just be in
there once so if we do like 2 107
it's in there once but if i re-render
you think okay well it's going to go get
me zero to 60 now so it should be in
there twice
but no react smarter than nice like well
you've already rendered this component
why should i go
and re-render it again i'm not i mean
i'm not going to come in here and say
um
yeah i'm not going to come in here and
say i'm going to re-render what's the
point nothing's changed the props are
the same so i'm not going to re-render
if the props happen to be different i
would re-render but i'm not going to
but this is where some people
forget that this use effect still going
to get hit
and you can see that clearly here
um so if you go to the network tab
search for two one zero one seven eight
or two so it's going to do the first
call which when it gets comes on to the
pit reacts loading everything the second
once it's rendered the third call
when you do a scroll
so we have to be careful with this
so one amazing thing you can use is memo
a memo works like amazingly so all we
have to do
just put memo there
wrap it in a function
say story
and this will prevent that use effect
being hit
which is really good because we're not
making additional additional network
calls this is one of my favorite um
things about uh the memo function how
easy well for hooks essentially how easy
it is to just implement that and that is
going to come back now and say okay well
if i'm in store a container and i
realize this is wrapped in a memo even
i'm going to go in here i'm going to
check to see if that's already on the
page and if and if it's exactly the same
i'm not going to do anything why should
i
you know do this twice
so we'll copy this id once more i'll do
a refresh
i'll clear this out
go in here save this save this
so should get a network call in here now
once so it's there once and if i just
remove that you can see there's a ton in
there if i go scroll down it's going to
go re-render
and you see it's only re-rendering
the new ones
and it's only in there once so no matter
how much i scroll
we're not going to be hitting that
network more than once because it's
already there
and that's memo and it's amazing i
absolutely love memoir it's my favorite
hook
uh we can get rid of that story id don't
need that
um
perfect
clear that out
do one scroll it's not in there perfect
if i do one more
it's in there once
absolutely love memo works fantastically
yeah and just react in general is like
really good i just really enjoy working
with react and um
don't get too uh put down or be too
harsh on yourself if you don't know
something like even i you know even
people experienced who've been working
react for three four five years or
whatever it may be
do forget stuff like
i had to sanity check myself just then
to see
um will this component re-render if the
props haven't changed and um you can
call you can't call a component to
update like with should component update
for the return um
and when i say return a re-render
essentially
um but yeah i i still have to sign it to
check myself i everyone forgets stuff so
uh don't get too uh down on yourself if
you don't you know fully understand this
tutorial i'm here to help i'm on twitter
the github's in the link the twitter's
in
in the link the link for github is into
uh the description the link for my
twitter's in the description
my email is uh
on my youtube channel so feel free to
check that out i'll answer all emails
even though it may take me a bit of time
but i'll answer every email
uh and
yeah just keep following the tutorials
we can run this through lighthouse now
actually let's just see uh performance
wise and i'll show you how to do this
actually let's go ahead and
do yarn build
and we'll create a production build here
creating an optimized production build
let's see
let's see let's see let's see
should give us part 5000 i believe
uh we can use serve you may have to
install this just do like yarn out serve
it should work uh there we are
and you want to run your production bill
through lighthouse um
if i open
a new version you want to run an
incognito so you don't get like um
look i mean even even here i've got so
much stuff that i'm trying to learn
everyone's still learning so even on my
you know task bars there's certain stuff
i forget so uh yeah don't be too hard on
yourself
um
click lighthouse little add-on you can
get from the chrome store run it
incognito so you don't get other
applications well extensions interfering
generate a nice report
it's running in mobile mode which is
nice and we see it's responsive
uh and boom we've got 95 performance
best practices time to interactive yeah
it's a bit slow serve static assets with
an effective cash policy nothing we can
do about that unfortunately whilst we're
doing it locally but if you put it on a
server it would won't run great
accessibility all passed
best practices again we can't hit 100 on
this because we're not using http http
2. we can do that on a server seo
progressive web app we've got a service
worker running which uh which is nice we
can't hit this to put on a server but
yeah you see like we pretty much hit all
bases you can keep re-rendering this
actually to get better scores
and they're probably one or two
extensions i've got enabled i think
you've got like last pass and a few
other things that are running
um there you are 100
100 performance it really depends but
yeah that's lighthouse um and yeah i'm
really happy with this hopefully it's a
good project that people can learn from
it's not too complicated
um
but yeah it's not too complicated
there's only like one component in there
but we're hitting apis and i'm so
excited to be looking at graphql next
it's gonna be so good to be able to you
know make this from one component and
render just one
api we're going to be hitting graphql
and getting a bunch of different
endpoints
so yeah that's pretty much it for this
tutorial i hope you learned a lot we did
react testing library we did one
component we looked at memo
implemented stuff like mappers utilities
for d-balance selecting fields we had a
service worker we did apis quite a lot
actually so if you got through this
congratulations
i'm on twitter carl hadwin
all the relevant
links are in the description below
this will be on github so that will also
be in the description below
follow me on youtube search my name carl
hadwin or cognitive search and you'll
find many videos like this and many more
to come and keep an eye out for the part
two of this where we're gonna be looking
at graphql that's gonna be really really
interesting
and any questions drop them below i'd
love to hear them so yeah let's uh as a
community maybe build on this try uh if
you get to the graphql point before me
fantastic
uh maybe we can do live updating too in
this that'd be cool so yeah any ideas
throw them across i'd love to hear them
thanks for watching this video
as always i shall see you in the next
one