Transcripts
1. 01 Inroduction to the course: Hi, welcome to this
course introduction to Tennis Stack query or react
query. My name is Babak. I'm a software engineer with around 13 years
of experience, and I used react over
the last seven years. And in this course,
I'm going to share my experiences with
Raquery to you. Let us jump to the contents and what we are going to
cover in this course. And first, I created some
Github repositories for you. In the first
introduction module, I will give you the
links and also I will tell you about what we are
going to cover in this course. In the Module two, we are
going to Bootstrap a 22 up. We are going to set up a
project with TypeScript, and also we implement
a Dutch service, and we implement the API
between client and server. And in Module three, I'm going to use rea query in action. So first, I will compare
rea query with redox and I will discuss
about the estate management solution and
what is the difference. And then we are
going to implement our first query and
our first mutation. And then we will refactor
and clean up the project to be a production
ready project. And at Motion four, I will also introduce
you to future resources that you can learn after
finishing this course. And what is the period
requirements for this course? This course doesn't have a
lot of period requirements, and the basic knowledge
of Java script and type script
should be enough, and also a basic
knowledge of the react. So if you are
familiar with react, the basic concept,
what is a hook, what is JSX, this course is a good fit for you and you
can start with this course. Everything else will be
covered during this course. So please join me and let us get started
this journey together.
2. 02 checking out different commits: I have created two
repositories for this project. The first one is RequeryTdApp, and this is getting
started with. This is the client
side application, and I have another
repository for the server. For every repository, you can manually download it as a z fle or clone it
with the Github. And if you go here, you will see all of the
comments that has been done to this repository. If you want to follow
with me step by step, I would suggest you can
always come and pick the committage and
inside your terminal, you can run git log
and you can see all of the commits that I
did for this project. If you copy one of
these committage, you can check out that
comitag what does this do? This will bring all of
the changes to here. So you can start from this, and then whenever I
show you in the video, you can do it step
by step with me. So if I run this command, then I am in the
place that I have been when I was working
on that part of the code. And in this way, you can
do everything with me. And if you want to back
to the latest version, you will just check out M. If you are using an ID
like Web Storm here, you have Git icon. You can also see all of the comments and all of
the changes here and here, I can also do checkout revision. What this does is my head of the Git comes
here and now I am here, I can start when I
see the second video, I can start coding, and then
this would be the last step. And if I want to just get back, I will just check out. A. So in this way, you can also follow with
me and do the coding. The best way to
learn is by doing. So I would also suggest
you to take an action. And whenever I start coding you and whenever you are
watching the videos, please also do the coding yourself so you
will learn it better.
3. 03 install react with create react app: So let's start by installing
react with TypeScript. I will use Create React app. This is an script
that allows you to easily install react without
a lot of configuration. So let us go to Google and let us search for Create
React app TypeScript. As you can see, the first link is Create React app website, and I'm going to the
installation section. As a dependency manager, I am using YR, so I will copy this command and let us go to the terminal. You don't have if
you don't have yarn, you can easily install it
with this common PML GR. It will globally install
yarn through the NPM. And as you are coming with
me through this tutorial, if you want to be sure
that all of the things works exactly like in my system, you can run this command, not dash dash version. So I'm using the
version 22.14 0.0. Technically, any version higher than this version should work. But if you want to
exactly make sure, and I also recommend to use
the exact same version. So if I face any error, I will also show you how to resolve this
error and you can come with me step by step
without having any issue. And the tool that I
am using to install different versions
of No JS is NVM. You can easily install any version that you
want with NVM installed. And then I have this version. And because I already have it, it says that this version
is already installed, and then you can use this version with this
command NPM used. Okay. So let's start and then I will use this command
that I have copied. As you can see it says
Yarn create react app. I will call it as a to do app, and the template
will be typescript. So it starts installing
and downloading the dependencies that is
required for react to run, and it will take some
time for the first time, and let's wait until it
finishes the installation, the required packages
and dependencies. Okay, perfect. Then
the installation has been finished
inside my terminal, you will see that I
have some commands, Yarn start that starts the development
server, yarn build, which bundles the app
for the production, Yarn test which runs the
test and yarn eject, which removes the tools that has been created
with create reactor. So let us go to the app, and here, let us see
what folders I have. So I have not my ****, my package dot JS on public SRC, the TypeScript configuration
file and Yarn No. I will start my project
with Yarn Start, and it asked me to allow it to access the port and perfect. As you can see, now react
is running up and running.
4. 04 create todo page: So in this time, I added some coding to make the project
looks like a todo app. Let us see what I have
added to the project. So the first thing that I added, I added a header to the Navbar as a Navbar
of the application, and we have the Todo app. We have a meno entry for the list and we have
a create Todo page. And for this, I have
used Bootstrap library, which is a CSS library, which helps us to
create user interfaces. And for specific react, I added react Bootstrap. And here we have a
list of the to dos. This is the idea of the to do, and this is the
description of the to do, and this is a checkbox to show if it has
been done or not. And then we have a
create to do form page, and here users can
enter the title and then set up the checkbox
if this is important, if this has done, and
then create to do. Let us see what I have
changed inside the app. So to see the changes, I created this is
the folder structure after I added some codes. So inside the after TS 65, I added the package
react Roadom. React Rotterdom is a package
that allows us to create navigation and create links
inside our React Rotter. So here you can see
that when I click, if I go to slash Create, this page will be shown. And if I press on list
or here on the two, then we will return
back to this homepage. How it has been done. Back Router provides a
browser outer class, and here I have a header, and here I have routes,
the first route, which is a slash will be
mapped to the list component, which gets a to do as an
array of to do elements, and slash create goes
to the create page. You can see, for now, I added I hard coded
a list of todos. So for now, I didn't add
any saver communication. There are just fixed to dos, which this is the description, and this is the first
to do second to do. And the first one is
important. Is true. So you can see that this
one should be okay for now, we don't have a column to do. But for example, I will change this and if
I refresh the page, I kill the terminal, let me start up again. And if I change this to through, you can see that it
has been changed. So for the create page, let us see the folder structure. So I have one header,
you can see here. I have models, which this is the definition of the
every Tu do has an ID, has a title, has a Boolean, which shows if this
is important and has a boolean which shows
if this todo has been done. And inside header, we
have a link to Slash, which is this todo
app, which is this, and then we have
another link to lash, which is the list, and then
we have the link to create, which is create todo. And inside Todo I
have two components. One of them is list, which as you can see, we have a table and these are the headers of
this table and inside here, I will read todos as a property, and we are iterating over
the studo and for each item, we will show ID title, and we will show a checkbox
and the condition that if this has been checked is that if this
Studo has been done. Inside create page, we have
a form and this form has a title, which is here, and then we have two
checkbox, the first checkbox, and the second checkbox for if this task is important and if this
task has been done. Until now, this is a
simple react project. It doesn't have any
communication to the server. I just added react router
package as the navigation, and I added react
Bote trap and let us go here inside our
package the JSON file. You will see that which
packages that I had. And here is the list
of all of my changes. So I added the header component. I added the todo. I created two files for create
listing to dos. Inside up to TS six, I removed all of the
boiler plate code, and I added the browser
otter and the header, and inside Git ignore, I added that idea folder
to not be included. And I added some dependencies, put a strap, react, buttes strap, and
react Rotter do. So I will commit this and I will give you the
repository leak so you can also check out and you
can start from this point, and you can check out my changes and then
you have this project.
5. 05 github repository: So this is the repository that I have created
inside the Github, and I commit and push all of my changes to
this repository. So the URL will be
Pima query two app. You can clone this repository from SSH inside your terminal, you can just run the command
Git clone and then copy this repository or you
can do it with SSS, or you can download
it as a Zip file. So all of my changes until now exist in this repository,
and from this point, you can check out
this repository, and then you have
all of my changes regarding the changes that I showed in the previous video.
6. 06 server app installation and run: Let's talk about the
second repository that I have created. As you remember from
previous video, right now, we have all of the todo app and todos inside the source code of the front and as an
aesthetic variable. In order to make the
app more realistic, I created a server application. And this server application
I have created with NGS. If you have not worked
with NojS, don't worry. You don't need to be an expert in Nojs to understand
what is happening. The project is really simple. So the only thing
that you need is to check out this
repository inside your terminal and then just run the command NPM install and
then node index dot js. Let us take a look at index js file and let us see what this
application is doing. The first line is
requiring Express. Express is a web server for NochS we don't need to go
so much to the details. The only thing which
is here is important is the port that it is 8,000. And here we are just telling to our web server that the
response should be in JSON. And here we have a list of
hard coded todos as here. And we have two endpoints, which is the first one
is a get endpoint which returns this list of todos. And the second one
is a post input, post request that allows us to send a post request
to slash todos. And then this will
create a new todo. And then it will push this to the list of
todos that we have. And at the end of the file, we will listen to the pot. So let us see this in practice. Let me open my terminal and
let us go to do server app. I already install it
with NPM install, so I don't need to
install anything. But for you, if this
is the first time, you just run it, and then I
will run Node Index Dodds. Here, you will see that
the app is running inside the local host 8,000. And the link that we can see to list of the
Todos is slash Todos. So I will go here and
I will add todos. Perfect. Now, I have a
list of the two dos, and I can see the first link. This is Buy groceries, has done is fast and
is important, is true. And the second one
is walk the duck.
7. 07 reading todos from server: So in this video, we want to make the app
more realistic by reading the list of the todos from the server that we have
created in the past video. So in order to do that, I will go to my IDE, and here inside our
app the Ts X file, we will see that we have this
hard coded list of to do. Let us change this to actually make it
work with the serve. I want to use a react estate, and I will call it data. And here we want to have an API call and fetch
the data from the seven. So let me use we will define
this as an use effect. Use effect is a react
hook that allows us to run a callback
when the function, when the react is
rendering this component. And here I will define
one variable as a state, and I will call it
data and set data, and we will use stats. And as we are using type script, let us call it todo type, which will be an array
of the todo type. And we need axios
and let us also call let us define the variable
that for the API, our API would be local host 8,000, which is the address
of our server. And in order to read the to
dos, this will be the pass. So XS dependent S
is a package that we can call the API with that. And here we are having
we are reading the API, we are returning the
response and we are storing it as a result
since us is Async. Since calling an
API is an Async, so we need to await until
this this has been done and then we don't since we are returning
the whole object as a resons I will
set it as a state. Let us see here. Let us add a console log to make sure
that our result is correct. We need to install the axios, so I will add it with your
add to our dependencies. Now I have install it. I can import it from my
package that Jason file, and here we also need
to set it as a date. And here we will
also add the list of the dependencies that
we have for this hook. Here I have an error
which says argument of type promise void
is not assignable. In order to solve this issue, I will define a
fetch function here, I will call a fetch
data function and I will put my definition
of all of my lines here. This function will be
async and I will remove the async keyboard from here and here I
will call the data. And here you will see a warning which for now, we can ignore. So, let's get started. Let me as you can see here, now I am receiving a network. Let us see what is the
reason of this network. So let us go to the network tab of the browser and let us refresh the page. We will see here that we have
to request for the two dos, and this one has been failed. And we will see
strict origin policy. So in JavaScript, since
I am doing an AgXRquest, this is one of the security
features of the browser that this allow the app to communicate with
another server which is not on the same domain. And because we are running our local host on port 3,000 and the back end our Node JS running on 8,000,
this will happen. So let us fix this. I will go and I will
open my server up. And here we can
use a middleware. I will use this CORS, and I will tell
that if the traffic is coming from local host 3,000, the preflight request could be. And we need a CORS
module for this, so I will add it as CORS, and we can install it
by adding CRS package. So let us go to the
terminal and let me let me start the process, and now our back
end is running on the port 9,000 and let us see. Perfect. Now I have the request. I see my results and
I have the data, and then we have
these two grosero. So with these changes, let me add my changes
to the Github. I will commu this as an
allowing CORS for clients. I will push my changes and let us close this project
and go to the client. And here, now we
have the result. So as you can see, the result, I'm printing
all of the things, so let us change this
to result data and the result that data should
be what we exactly expect. Which is the first one is
ID and then by crossers. And now that we have the
data from the back end, instead of this variable, let us pass this. Let us call let us pass data to this and let
us remove this too. And at the first time because the variable has
not been defined, and let us define it
as an empty array. Okay, so good. And as you can see now, I have these two objects, I have this and these datas
are coming from the back end.
8. 08 sending todos to server: In this video, I want to work on the second tab that we
created on our application. Now that we have the
list coming from our backend and this
data comes from the API, I also want to link this form to our backend and make sure
that this data will be also transferred through the API to our server and it will be stored into the array that
we have defined on our API. So let's get started. But first, let me
just comment and push my changes from the last video. It's always a good
practice to commit frequently and keep the code clean for every piece of
changes that you made. I will say, I will add
a commit message read to those lists from API. Let me come and
push these changes. Okay. Then let's
get started with our create form that
we have used for this. Here, I have an
aesthetic form now. I want to change it and to store the values inside
the react estate, so when user process this
create to do button, we can submit the
data through the API. So let us define an
estate variable for keeping the Data, let's call it. Let us call this as to do, and the type will
be the todo type. So let us check the todo type
that we have defined here. We have ID title is
important and has done. And since here we are
going to create a todo, and this todo does
not have an ID, and this ID will be generated when the API assigns
this to a database. Let me make this ID
optional for now. And here I want to have an unchanged handler
for my form and I want to call this as an event and I want to
define a function as a set title and then
pass the value that I am receiving from
the four let us define this set title function. It will be we will get a title as an
strength and we want to store it as inside the value to the object
that we have created. And if you are not
familiar with the syntax, this is an ES syntax that
I'm using a spread operator. And here I am telling
JavaScript that I want to have a new object with all of the properties from
the previous object, but I'm going to override
the title value. So everything will
stay the same, but the title will
be this new value. And also in ESX, we have this that if the key
and the value are the same, I can just make it more
simpler like this. It is short. And now we have an error here and it
says that it is not assignable to this because some of the values
are undefined. So for the initial value, let us create an empty object, which the title will be an
empty string and is important, will be false and as
done will also be false. And for now, just let
us make sure that this function that we have
works as expected. I want to see the title inside my console whenever user
changes the value here. Let us test this and let us open our console and let us
write new to Okay, cool. Now you can see that I
have all of the values. So let us define the
other function as well. Let us also define two other function
for set is important. And the value will
be as important, which is a boolean. And I will use
just as important, and also I will do the
same thing for has done. And inside my form control, I will also add one change, and this will be an event. And here I will call set is important events that
target that checked. And I will do the same
thing here, here, I will also define an
event and then set has done will be events that
targets that checked. I think I didn't replace
it here, set has done. And whenever user
submits this form, let us have submit handler, which I call it submit. Let us define submit here. And for now, let's just log our todo object
to make sure that we need everything right. So here I will add
a value and let us. As you can see, the page got refreshed when I
press this button. Let us prevent the page from refreshing by passing
an event here and by preventing
the default behavior of the click event which
is refreshing the page. And now we have this type of let us go and see
what is on submit. Function is, this is
a form event handler. So let us define this
as a form event. And let us see this time
we'll call you to do cool. Now I have the value here that has done is false,
is important too. So if I create something else, then it will be both
of them will be true. And if I just remove this, then it will be false. Now, I am sure that
the object that I am creating is here, correct. So let us go and call the API with this
object that we have. As you can remember from our list object from
our upto Ts, it's fine. We have created a use
effect inside use effect, we had this fetch data function which we were calling the API. And now I need the
same API variable. So let us put this inside the folder and let us
call it as a constant. So I will create a new folder and I will call it constant, and inside there, I
will create a file. I will call it API, and I will pass this
value to there, and I will export
this as a variable. And then I will here, I will just import this. And now inside our
create object, we want to also call the API. This time, the API
will be type of post, and we will also call it
with the Todo object. To call the API, I will use axis dot post method, and here we can also have another object as some
kind of parameter. Then I will call
this as a todo and the value will be the
object that we have. Let us also add a console
log for the result. Let us go and call this new
todo, and it's important. Create todo. So we have
a bad request here. Let us see the server response. And in valid to do format. So let us check our servers
to see what it is expecting. I will open our server
code in this new window. So here we have defined
slash to do that we expect the request and the
title to come from the body. As you can see here, I have read all of the fins separately. So let us change our client to also send them in
a separate field. So let us call this as an title
to do that title has done will be to do that
has done and is important will be to
do that is important. Let us call the API
again and wonderful. We got a response. The ID has been saved, and now we have the four. And here, the main
challenge starts and that if I go back
to the list page, I will only see two objects, and I have to refresh
this page until the data gets populated
from the API. So let us see what is happening. And if I go to
create Tulu tab and I create another and two. And for example, I would
say is important for us. This form will submit, but inside the list, I cannot say I cannot see it because this
is a different component. And these different
component has no way to communicate to this
other component. And in the next video, I will start talking about the global estate and the way that previously we were solving this
kind of problems. And then I will show
you why Raquery is a better solution and how we can implement this with react
9. 09 State management Solution: But how we can solve
the problems that we have seen in the
previous video. The first idea is like to put everything into
the one place. So let us keep all of the data regarding the
two dos in one place. And this was the concept of the store that let
us have an store that keeps all of the data and list components instead
of calling the API, reads the data from this tore, and the create component puts
the data into the store. So whenever we are
creating a new todo, create component will put
the data into the store, and then store notifies all of the other components like list component that the
data has been changed. So here is the new list of the to dos that
you should render. And list components will be re rendered and with the new data. And in this way, we can have the communication between
these two components. And this was the
idea of the redox, and Redox implemented this as a solution for the
estate management, one of the libraries that provided these
kind of solutions. And I personally used
redox in the past, and I really enjoyed
working on it. And the concept is
like that let us separate the representation of the data from the data itself. And in redox, we have a concept of the store that all of
the data that will be kept inside the front
end and will be shown to the user will be kept
inside the store, and the other components are
subscribing to this store. And whenever some
kind of data changes, these components
will be notified and re renders these components, and then they will
show the DO value. Let us see the
redux architecture. Here, we imagine we have
an application that uses that stores the
value of the user, the amount of the money that he has inside his online valet. And now we have some kind of action
inside this application, we can deposit, we can withdraw
from this application. We want to have a
single page application that user sees his
balance all of the time. And in redox, the concept of the concept is like that
we have a UA user interface, and everything that user
does is kind of an action. For example, if a user clicks on a button,
this is an action. If user fills the data inside
a form, this is an action. And whenever an action happens, we have a dispatch function
which triggers this action. That, for example, in this case, in this video that
you are seeing, at first, we have a
balance of the zero, and now user triggers a deposit. And this is a button
that, for example, it clicks on Deposit $10. And this will trigger an action. An action is an object
which has two properties. One of them is the
type of the action, which in this case is deposit. And the payload is the actual
value that this action has, which is in this case, ten. So whenever user does this, we are triggering an
action which is type of the deposit and
the value of ten, and the S store is listening
to all of the actions. And inside the store, we have a concept
of the reducer, and the job of the reducer
is to get action and process the action and update the state on this based on
the action that is happening. For example, if the first value of the ballot of the balance of the ballot
of the user was zero, and then we added an action
for the deposit of the ten, the reducer will
sum the zero with ten and puts this new ten as a new value for the new balance
as ten inside the store. And this is the whole flow and all of the other components
that are interested in the value of the balance will listen and
when this happens, a store updates and notifies
all of these components. And if, for example, if you
have a header component that shows the balance inside that, this component will be
notified that the balance has been changed and then
it will be re rendered. And this time, as a balance, it doesn't get zero, it gets ten, and then it renders
this ten as a neo value. So in this case,
we can communicate indirectly between
different components that are working with the
same set of the data. And this this helps us to
achieve our goal and to have a single page
application that users don't have to
refresh the page, and different parts
of the application will communicate
through the store. So whenever the data changes, all of the relevant parts
will also be updated.
10. 10 Redux Cons: I personally use redox
in a lot of projects, and it is a wonderful library. It's a really good library. But there are also
some disadvantages when we are working with redox. And in this video
and in this lecture, I'm going to talk about
these disadvantages. The first thing is actually redox needs a lot
of boiler plate. So we need so much
coding is required, and most of the coding
is just templates. So for example, we need
action action creator, and actions are type of
objects with type and payload. And we should write
all of this code, which is a really
simple objects, but it is all the same and
the same and the same, and it requires a lot of time to writing all of this
boiler palette code. And the second
negative part about redox is that redox doesn't
provide async logic. So the whole architecture
is based on synchroness. So user triggers an action, we have a reducer and this reducer changes
the data in the state. And then after that, the
components that have registered for the state
will get the updated value. But if we want to, for
example, call an API, which is an Async operation, redox doesn't provide
a solution for that. Usually, you have to
manually build it, or you should use a third party library like
redox Tank and redox Saga. And every third
party library also provides a learning
curve for the team. So your developers should learn this new technology and should be familiar with
working with that. So this is the second cons
of working with redox. And the third disadvantage
is that redox does not have any built in
caching mechanism. So if we define an API call inside the redox that
if an action happened, an API should be called and
the data should be fetched, every time that this
action will be triggered, the API call will
also be triggered. But if, for example, we know that in the time
frame of 5 minutes, the data won't be changed and we can use the caching
version of the data, then we don't need to
call this API every time. And unfortunately, redox
does not provide this. TNSaquery by default provides
a caching mechanism. So every time before
calling an API, first, it will return the value
that's already in the cache, and we have different
options that we can say what will be our policy
regarding this caching. And this is a really
helpful feature. And the last and
fourth disadvantage about redox is that redox does not provide any
garbage collection method. And what is a garbage
collection in programming when we have some objects that
they are not used anymore, and there is no reference
to those objects, we call them garbage. And this has been introduced
first time by Java that, for example, in Java, when you create an object, you have a reference
to that object. But if you remove
this reference, that object stays on the memory. But because there is no
reference to that object, your program cannot
use it anymore. And Java has a built
in system that detects this kind of the
memory and then removes them. And this whole process will
be called garbage collection. And in redox, when we are storing some values
inside our estate, Redux does not provide any
garbage collection method. So if we store data inside our estate and the program
doesn't need it anymore, it will stay on the state forever until you manually implement a garbage
collection method. And this is also a disadvantage. On the other side, TNStaquery provides this functionality, and we have a garbage
collection that makes sure that the
data that is not required anymore will be deleted from the estate
and from the memory.
11. 11 Writing the first query: So let's get started with
rea query and let us see how rea query can help
us to solving our problem. So first, we need to
add the dependency. I will install the
dependency with, add a stack slash React Query. So as you can see
inside our package, Jason, we have a new
entry for Raquery. The version that I am
using is version five. So now we install the Raquery. The next step would
be to set it up. We need to wrap our
app with a provider. So here I will go and inside
our browser rotor here, I will create a new
query client provider. And I will wrap the
whole thing here. And this requires a new client, which we should initialize it. I will also Raquery
also provide this, I will call it as
a query client, and I would say
new query client, and I will pass this
query client here. And I will also import
this from Raquery. And now we have wrapped
our application with the query provider and it
allows us to use rea query. And the next step would
be actually to go inside our app component and here
inside this fetch data, I'm going and I'm going to
extract all of this code and put it inside RaqueryHok. So the way that rea query works
is like we define queries whenever we want to have
a data from the API, and this will be called query. And whenever we want to
change the data on the API, we will call the mutation. So here for this one, for the list a TC and for the list component that are reading the data from the API, I will create a query. And for the create
to do component, which actually changes
the todos list on the API and
creates a new todo, I will use a mutation. Here, instead of calling the
API inside a use effect, I will use rea query syntax, which is a like this data and is loading. And we have a
function from query, which is called use query. And here inside the use query, I will pass an object, and this object should
have a query key which acts as a unique
index for this query. So I will call the
query key here. To dos, and there will
be a query function, which we'll call it query eN and this will be actually
the API call that we have, which we will call the API, and then we only
need the data part. So I will use I will remove
all of this use effect. And I also don't need
the data here anymore. And because this is an
asynchronous action, a query also provides us a boolean which shows if
this hook has been called, if this use query
has been called. And if the app is
still in loading, then I just simply return
a paragraph with loading. So let's start our app. And let me move
this function and also first let me move
this function inside the list component because now we don't want to pass this as a parameter
to the list component. So let me grab all of this code. And here I will change
the list component to read the data from the And I will use it as a inside the map instead of reading
them from properties, I'm going to read
them from the hook. And to do will be type
of the todo type. And now you can see
that actually I have all of the to dos,
which is amazing. And let us do a little bit
cleanup about the project. Now I don't need this
property type anymore. And also, let us go
to up the T six file. We don't need all of this input. And now, as you can see, also the separation of the
concept is really better. Now, I only define
a query client. And then inside the provider,
I will provide this. And inside the list component, component is calling this
API and uses a query, and all of the use effect
has been replaced. And this will be recognized
as a key for this query. So what is the most
interesting thing about rea query is that in the next video when I
start editing the query, and when I am starting to adding a new to do
to the to do list, these to dos will be
used as a unique key. And whenever that's inside
the create component, we are doing a mutation and
we are updating this key. Now, Rea query knows that the key something regarding
this key has been happened, and then it automatically
re renders the component, so the last component can
be notified about that. Let us commit change let let us commit our changes and then let
us join to the next video. I will call this using react query to fetch
to those lists. And.
12. 12 Writing the first mutation: Okay, let's change
our create component, create page to also
use rea query. Let us go to the
create component here. We have all of the source code, and inside the most
important thing is submit. And here previously we
were calling this API, and then we were putting
the result here. So now I'm going to
define a rea query hook. This time, I will define
it as create to do. And this one, I will use the
mutation of the rea query. And as query, I can also provide an object
to this mutation. And here, instead of
calling query function, we will call it rea query
causes mutation function, which is mutation FN. And here we can actually
call what should be done. I have a to do, which
I want to create it, so I will pass it as
a parameter here. And here we will do
this as the API call. The function will be the
API that should be called. And and also this object provides us a handler
which is success, and this will be
called when the API gets resolved and when we get
the answer from the server. So here I will
just add a console like that for now to make
sure that the success, and then I will just
print the data. So I created the mutation now, and when the form happens, instead of calling the API, I will just call the mutation. That mutate, and I will pass this object this
pudo as my object. I don't need this because I already defined it as an object, so this can work. So let us go and let us open our console and also our network to
see what is happening. I'm going to call this
todo with react query, and that is important
will be through. So as you can see,
I have the react, the data has been transferred. I have the query, and inside, I have my ansecs. And let us go and let us see
the list, and wonderful. You will see that I already
have the value here. Let us create another ticket. I will call it another test and I will pick the
post for to do, and then I will
just return and you will see that I already have it. Now that we have come so far, let us go and lets us
make our app better. So I created two different
pages for the phone, which is one for submission
and one for the table. And in our home page, it is also again
showing the list page. Let us make the app a simpler and have a kind of let
us put the home as a dashboard that user can see the list of the
tables and also can create the new
todo, as well. So I will go inside my app
the T six file and I will replace I will add
another route, and for here, I
will use the list and And here inside my app six foil, let us search for create todo. We had the navigation, and here we will pass
the list to the list, and then here we will
change the up to that. So now here we should see the list, we should
see the create. And for the index, we're still
using the old components. So let us create an
index component. Let us call this as a homepage. And our homepage should be a component that
renders both of these. So here inside my homepage, I would define an homepage, and this will be
a rear component, which we will return create which will retain what was the name of
the create Create page. And then we will
also have the list, so I will put the
create page here and also I will use the
list page here, and I will let us import these two components and let us export default homepage
and inside our Udot 65. We want to import
also the homepage. So good exact. Now I have a list page, I have a four create
and here I have a Todo. So let us start testing our app. Now we have this list page. We have this create to do, and now we have our homepage. And here I will create another
to do for petting dog, for example, and I will
pick the two things, and then I will create to do. And you see nothing happened.
So what is the problem? And let us go to the list page, and now I have the
petting dog here. But if I return, like,
Okay, now I have it back. So there is an issue here
that I want to discuss it. So let us create another task. I will just call it
ten. Let us create. And you see when
this is happening, this component
doesn't get notified. And this is the reason
that we define the keys, but we didn't tell the rea
query to update the keys. So when we do this mutation, when we are calling this API, we know that the todos which exists on the
API has been changed. And inside the success, there is a way that we can
tell rea query that the previously results that you got from the API
no it's invalid. So I will do it by calling
invalidate queries. And invalidate queries,
the thing that it does is it tells the rea query that the
previously fetched value that you have for the list
of todos is not updated, so you need to call
the API again. So I will and here I also
need the query client. So let us go and
we need this file. So let us create a new file. Let us I can also
put it in constant, but let me create
a folder for it. I will call it a query
clients query and let us call a new file client
that six and let us put this line there
and export it. And here, let us use query
client from that file. And inside our pudo
inside the query, we can also import
the query client. And and here we have
an invalidate queries, and I will use the same key that I have used previously to do. And this will tell Rhea query that this key has
been invalidated. And then you should
refetch and here I need to tell which kind of query key I want to invalidate. So I will use query
key and then todos. So let's see it in action. Let us go and see our app. And this time I'm entering 20, which is important,
has done wonderful. You see that this
immediately happens. And let us see our
network request and let us see what is
actually happening. So if I change this to 200, when I am pressing
Create, first, we have a perfid request, which is related to CRS, and then we have
a create object, and then this case will
get the new list of to do. So amazing. Now I can
work with the app, and easily, these two
components are communicating to each other without even
knowing that they exist. And I can see my changes
immediately here.
13. 13 showing progress bar finished todos: So I just restart the server to return back to the initial
values that we had. And until now, we have
created our first query. We have created our
first mutation. And now these two
components are completely connected to each other
through the rea query. And maybe until now, you were asking yourself that
it is not so much benefit because we just change one API call and change
another APL call with query, change another one
with the mutation, and maybe this is not so
much worse to use it. But now I will continue
my coding and I will expand the project and you will see the rapid speed
of the development. So for this video, I want to divide this section to two section that
the first section will be the creation to do. And the second section would
be the number of the to dos that have been done and the
number of the old tots. So it will give us a feeling
about how much we have progress regarding our tutliH many of the items
have been done. Let us do it, and then you
will see how much easy and how much quick I can add
this to my project. So let's get it started. And here I'm going to
our homepage component, and let me close some of these
to make it more simpler. And here I will add a row
which is coming from react, put a strap, and it allows me to have two different
columns on the same row. And here I will add a coal and I will put the first one here, and for the second one, I will just write second
and let us see the changes. Okay, cool now, we have
this section and we have another section and also because the row doesn't
have any container, let us put the least page
inside the container. So let me bring the
container out of the least page and let
us put the container here and let us remove the container
from the least page. And with this, it is also better because now the list is actually only one
table component, which is what it should be. And also, I can also get
rid of this ETGsS tag, so I can just do this better, and it still looks good. Okay. I have here my task
and this is the second task. Let us create a new
component which we'll call it as a progress. And inside my
progress component. Is let us render for
now just second and let us export our default components and let us use progress
inside our compag. And now we have the second
here. It's all good. And here we want to show the number of the
todos that has been done relative to the
number of the todos. So I will just use the
same code that I have. I can easily simply with
the same rea query hook, I can get all of the
data from the API. And here I will also add this line if it's
loading, return loading, and here I will show
I want to also have one array for the
finished to dos, and it will be that map. And let us for now, item, item that has done, and the item will be
a type of to do type. So let us use the power of
the typescript to do type, an item that has
done equal to true. Okay. I can simply
just write item data. And here I want to show finished items that length. And then I just want to
have some separator and then the whole to do length
and data that's length. And let us see it.
Perfect. I have two tasks. Both of them have been done. Let us add another task, we will call it not
finished to do. And I will just create it. And here you have
seen that it has been immediately
changed to three, but there is something wrong because we are getting
the same number. But as you can see, I
could simply create another component that it attached to all of
these other components, and all of them will be synced without even needing to know. And the only thing that I need
to know is the query key. Let us see why this is
item that has done. Let us add a console
that for data. And I think that's the
reason because we should put this outside and let
us see the console. So I have the data as an
array of three and oh, sorry, I should use filter here because I'm just interested in getting the items
that have been done. So that was the
issue. Okay, cool. And let us see. Now, another not finished to do another to do. And here I will select this. I'm expecting it to
be two out of the five, two out of the four. You will see how much my app reacts and it is so
much responsive, all of the changes
are happening, and there is no need
for updating anything. And there is another
thing. Let us see the network request, and this is really one of the greatest feature
of the rea query. I will add another task and let us see what will
happen through the network. So we have one pre
fluid request, which is asking for
the service for CRS. This is the to dos, which
is the post request, which is creating
This is the post. The status code is 201 created. The payload is these values. And this is the
actual to dos that are getting the
response from the API. And these are the five to dos
that we have which three of them that has done is
true for three of them, and two of them are false. And this is really wonderful. Even when I have two
different components, and these different
components calling the same hook there is no
need for second API call. So Rea query understand
that this key is unique, and it only calls the API when we are
invalidating query here. It's only calls one API, and these components
will get the NO values, and also these components
will get the NO value. And this is one of the
really coolest features of rea query that I really like.
14. 14 refactoring and cleaning up: Okay. And now, let us start with a little
bit refactoring. There are some
things that we can improve inside our source code. But before starting that, please consider how much this
solution is simpler than redox that if we wanted to implement this with the
estate management library, we should create and here we
should have create an action triggering that list of the
todos inside the estate, and then the estate
should be the reducer, and this component should
have been listened to it, and this component should
have been listened. And all of the boilerplate, I could get rid of
it with rea query. And right now, I can make even the project
more simpler and easier. Let us do it together. So, as I mentioned previously, the query key is one of the important part
of the a query, and this is the connector
between different components. When inside our
create component, when on our success,
when our mutation. When we are invalidating
this query, this will tell a query to fetch to call the API again and update all of the
necessary changes. And the query key, we
define it as a string. So this is a little bit risky, because this can be easily mistyped and sometimes
it leads to error. Let us go and define
a variable here, I will call it export
cons to do key, and I will call it to everywhere
I will use and we can also defines let us define
this as an object export. React query keys inside this, I will define this as an Tu Dos. And here instead of
the Studos I will use todo key, and again, I will search for all of the quids and here
I will also use the Tudoky and inside
my progress component, I will also use the Studoky. And the only definition of
the ring will state them. The other thing is we have done the same thing that we are always
reading is loading. If this is true, then it means that this
API has not been resolved. This promise has
not been resolved. Let us also create a
component and let us call it loading's call. And the loading component
will be this one. I can simply write it in
just one line instead of So let's call this da
component, loading component. And here we export this
as a default variable. And let us if this, then we are going to return loading components and also we will import the
loading component. And we had this also
somewhere else. So let us also it's
a loading component. And yes, now it's better. Actually, we have all of the
things in the same time. And let us just make sure that
we didn't break anything. So I'm going and I will
add completed pudo. I have four out of
six and has done, the checkbox is correct. So all good, everything
has been done as expected.
15. 15 showing important tasks counter: So far we have so much fun
with RequeriUntil now. Let us add another component. I want to add another
component that shows the number of
the important task. Let us go and let me just copy the progress
component and let me call this important let me call
it important to do the Tsix. I will call this important to those and in the exact same way, I will use the rea query and the key will be the
same if you are and here I will just call
this important to dos, and my condition would
be is important. Then here inside my JS you
say you will have to do. Let us also use this
in our homepage. Let us also call this
important to dos. The We have an error object or not object with keys ID. If you render a collection,
you use an array. So let us see why, I should have a
lens function here. Let us also add a line
break here. Okay, amazing. Now, I also see one important. Let us create a
task both important and done an important task. I will checkmark boos you
will see it immediately here. The checkbox is here, the number has been updated and all of these have been updated. I really like to show
you how quick you can develop your app and how quickly
you can change your app. And this is wonderful with
the power of the reacquery. And now, if I add another
task, which is, for example, the important is true but has done this number
should reach to three, but this will be
five out of eight. And you will see this
is a unique experience that a user immediately
sees all of the changes. And there is no loading. We have a completely
single page application and it is so fast. And let us also see
the net work up. Let us create simple task. And as you can see, again, Rea Query doesn't send
any unnecessary requests. We have only this
one for the to do, which is the creation
of the task, and this is the post. And all of these
three components, there is only one API call, and this is also wonderful.
16. 16 automated testing: So let's start testing
our application. Now that we have implemented some features in
our application, we want to add some
automated test. But what is an automated
testing and what is the difference between automated testing and manual testing? So an automated test
is a test that will be run automatically without any interaction of
the users and humans, and it checks something
inside the software to make sure that it works
as it is expected. Relative to the other
methods that manual testing, there are some advantages
over for automated testing. Usually developers, when
they develop feature, they are testing manually. But when the projects is getting bigger and also especially in the production environments, there should be
automated tests because humans can always make mistakes. And there are advantages
of automated testing. The first is that
we can catch bug really early instead
of deploying the product and shipping it to the customer and then
receiving a phone call from the customers and users that they cannot do
something in software. An automated test at the earliest stage shows us
that something is wrong. And it also allows us
for safe refactoring, so we can refactor our project. And if we are in the
middle of refactoring, we are breaking some of
the old functionality of the softwares that we
don't know about it. If that part of the code
has an automated test, then those tests will fail, and we can easily understand that because of our refactoring, something has been broken. So we can address
also this issue. And automated testing also helps us to speed
up the development. We don't need to
spend so much time to understanding everything
and always be stressful, always be afraid that if I
change this part of the code, maybe other parts of the
code has dependency to that, and it will also increase our
speed and our productivity. And it also helps us for the
documentation because in test we show exactly what is expected for a
component to do. And everybody every developer inside the team
which sees the test can understand what is the expected behavior
of this component. And there are three kind of
testing that in this course, we are going to work on it. The first one is a unit testing, and unit testing is to actually test only a small
unit of the code. When I say unit, it means
it can be a function, it can be a class, it can be something that it is isolated from the
other rest of the code, and we are testing
each unit by unit. For this, we are going to
use est, and after that, we are going to add some
integration testing, and we are going to use
react testing library. Integration testing is a level
higher than unit testing. In unit testing, we are interested in just one unit
in integration testing. We want to see the whole
component and we want to test the whole component and see what happens if the user, for example, clicks on something and we
want to test that. And in the end twen testing, we are actually testing the whole application from
the view of a browser. So we are launching a browser, and then in this browser, we are clicking on something and we are viewing some pages, and then we are checking that some specific elements should
be existed in this page. Or after clicking this button, this should happen, and this is what we are going
to do with playwright.
17. 17 writing first test: So let's start with testing. The first step of the
testing that we want to cover in these videos
are unit testing, and we are going to
use for unit testing. Let us see our package
to JS on file. Here in the script section, we have one section
for the test, which as you can see, runs react scripts with common test. Because we created the project
with create react Act app, it automatically
added this script for us and we can run your test, and then it will ask which kind of test
do you want to run? I will press A to run
all of the tests. Sorry, I press Q and
it has been quit. Let us run it again, and then let us press A. So let us see. It goes
to SRC up the T six, and here we are getting a feed. And the other way to run test, if you are using webstore, I can also open a test file, and here I have an option for run up to test to Ts six file. And this allows me
to run this test. And I can also see
the same results back here in my terminal. But why this test is
failing because we already change after T six file, but we didn't update
the test file. So this test f has been
generated by create react app, and this was the default test, and we changed up to T six file, but we didn't update the test. For now, let us first
ignore this test file. I'm going to first add some other tests which
are simpler to write. And then in the future videos, we are returning to this file and we are
going to fix this. Let us go to our to do. For there, we have
different components here. This is the create component, import to do component, important to do components,
list and loading. And the loading component
is a simple component, so let me start writing with this test for this component. Will create a folder
and I will call it underline underline tests. This is also a convention
that you will see a lot in the area
community that we will put all of the test
files inside slash tests. Let us add a file called
loading test T six. Here, I will add a describe
column and I'm going to right loading component. And this describe shows that I'm going to test this component. And inside this test suit, I have multiple testers. I can add, for example,
render correctly. And I'm expecting that when I am running the
loading component, the written value would be a paragraph which
contains loading 33 dots. Let us go and let us render
the components and I will going to render
loading component and this component does
not need any properties, so I will just write like this for rendering of the component we are using
react testing library. So I'm importing render from testing library react.
And what does this do? This actually renders
the whole component, and then I want to make
sure that inside my screen, I will see this text. And for this, we are
also again using testing react testing
library. There is a function. There is a object screen that I can import
it from react py. And here I can go get by text. And I'm expecting these t
to be inside my document. So this will be my
first test case. And we are going to expect
a screen that get by text, and we are expecting this the result of this expression
to be inside the document. Let us run the test and perfect. Now the test is passing. Let me make sure that
actually it is working, so I'm going to change
it with another L, and this test now should fail. As you can see, the test
is saying unable to find an element with LLL
loading because this is wrong. I'm going to return revert it. And now we have the test. So in this case, I am sure, and for the rest of the project, if a developer comes
and by mistakes, put something here,
this test will always capture these kind of errors and we'll make sure that this will never
happen inside the project.
18. 18 code coverage: There is an important concept
in automated testing, which is called code coverage, and the code coverage
shows when we run the test how many lines of our code
will be tested with the test. So if I have, for example, a file which contains
100 lines of code, and I will add some test cases. And these test cases, when they getting run, they only run 60 lines
of this 100% line, it means that the
code coverage is 60%. And the code coverage
shows us our tests, how much our tests are good. So if we have a
high code coverage, it means that most
of the lines of our code will be covered
with the code coverage. And if we don't have this value, then it shows that actually our tests are not
covering so much. So it means that we can have
some box and some changes. And because there
are no tests that actually runs those
part of the codes, our software is possible
to have errors and box. Oh, hope you can get
the code coverage issue I here I'm going to write
click on this element, and I have another
option which is run loading the test the
TA six with coverage. If you are not using webstore, you can also run this inside the terminal with a
command R test coverage. And what does this do
is it will run all of the test files and it also
calculates the coverage. And here we have
different values, STMT. It shows the statement, the branches, the
functions, and the lines. This hundred means
it means 100%. So it shows that actually all of our code
has been covered. And this is here, correct
because our component is simple and we can have
only one lines of code. So this shows that when
we added this test, when this test has been run, all of the lines of
the code has been executed and so we will
get 100% coverage. And when you run this command, you will also see a
coverage for there, and this will give you
a LCV report format. And inside there, I have
an index at HTMMFle. I can run this, which opens
it inside the browser. And here I can also
see the code coverage. And here you will see
for the statement, for the branches, for the
functions, and for the lines. I have 100%. There
is only one line, one line from one line
has been covered. This is also correct
for the functions, and we don't have any branches, so there is no I and
that based on that, code runs differently,
and we had two statements and the two
also has been covered. And what is the difference
between a statement? A lines is that I can have multiple statements in one line. So if I start writing something like this Actually, this is three statement, but it has been written
inside only one file. And this is also the difference between a statement and lines.
19. 19 migrate to vite: As you remember, we had an issue with
our after TS six so that whenever I
run the test here, I will get an error regarding the axis and it says
that cannot import. The reason behind that actually we are using ES
module syntax in this project, but create react up by default has
been configured to a common Jz motion format, and this creates a problem. And to order to
solve this issue, I want to migrate the project
from create react up to IT. And which is a tool that
the API is exactly similar like JS and we can run it for building our app and
also running the test. So let us go and upgrade
our project to use Wt. First, I'm going to
remove react scripts. And then I'm going
to add Dev wt. So I'm installing it as
a dev dependency yard. And after that, we need to create a confict
file for the WD. So I'm going and create
a file and I will correct with that conf dots, and I'm going to put
this value here. So we are importing
react and define config, and you are going to also
import the react plugin. And for here, we also need to install with JS plug in react. I will also go to the
terminal and go you're at that's amid Js
slash plug in R. Now, we also have this
dependency and let us go to our package JSON
file and also let us update our dependency. So I will replace the build
instead of react scream, we will use What field
and instead of test, we will also use WIT test and I will remove the inject
script and for the start, I will just write wit. With also needs to have one index ML file inside
the root of the project. So let us go and create
an index file and let us put this value of
this HTML inside that. And I will also go and call this updatsx one
because inside our SOC, we have up Ts six so
let us go to terminal and let us add with run
inside our package start. Now wit is running, so let us see the 51732 use as a shot to expect some let us also at the dash dash host here. And let's run as R start. Now we can see our app because I don't have
not just running, so we also need to run our backend let us
also go to a terminal and let us go to server app
and let us run our server. And now I'm going and
refresh the page, so I should also be able
to see the project. Actually, this is sorry, this is a mistake I
should have given to index HTML our index t65. That's our app. So
let us I'm perfect. Now we have this and because the port of the
project has been changed, previously, we again
see the CORS issue. So let us change the
WIT configuration to run the port of the 3,000. And to do that, I'm going to that configuration
that configuration. And here I will add
a parameter server, and for the port, I
will go with 3,000. So let us go and turn a 3,000. Okay, perfect. Now
we have our app, and we are using WIT for
running our application.
20. 20 run tests with vitest: And now let us configure
what to run our test file. We migrated our
project to WIT so we can be able to run
our upper T six file. So let us install the
dependencies for testing of what. So we will need test, we need testing, library react, and we also need
testing library JS dum, and we also need the Sum. Uh Okay, I should
not write weeds, but yeah, to start
the dependence. And now we install
the dependencies. So let us go to our W dot comf Ts file and let
us add a section for test. And for the testing, we are going to add
set the global to two, and our environment will be JST environment that
the test is going on, and we are going to create
a create one setup file. We will call it,
setup that's Ts, and we are going to also exclude test some folders that we don't want to
be excluded for that, we are going to keep the values
that already existed and we are going to add everything
from into a test folder. Now we need to create this
setup file so let us go and call let us call it
setup tests to be more. Here. And we also change
this set of test. And here we need to
import testing libraries. So I will put this value here. Let us go and let us this time, try and run the test. So let us add also the
commands for running the test. Let us go to our package, Jason. And here for the test, I'm going to write V test run. And we will also add another
option for watching, which every time, if the
file has been changed, we want to re run the test. And with that, we can
also add another command. So let us run test. And perfect. As you can see now, this test is still failing, but we don't see
the error relative to axis because the test has
been configured properly. And from now on, I can also run this test and you can see that I have this test is actually,
I can run the test. It is failing because
I don't have react. Let us go and for now, you can ignore this
test because we will rewrite the
test in the future. But for now, I just wanted to fix the
error with the axis. In the next video,
I'm going to write test for the last
component that we had.
21. 21 write test list component: So let's continue our work by writing tests for
the list component. And what does the
list component do? The list component
uses TNSA query, and inside Tan SA query, we have the query function
we call the axius. We call the APA through the
axis and then reads the data. And if the data has
not been resolved yet, it will return a
loading component. So let us write a test for this. Let me go to the test folder. Let us create a file, let us call it test,
list the test. And here I'm going to add a describe log for
the list component. And inside my test, I will say it should
render a loading if the API has not
been resolved yet. And here I'm going to
render my list component. And let us import render from testing library
and also let us render. And what does the
loading component is? It is a paragraph that
only shows a loading. So let us go and let
us import a screen. And I'm going to
say a screen that expect and loading to
be inside the document. It is a simple test and
let us run the test. And you will see that the
test is failing and it says, No queric line says, use querclinePvider to set one. And why this is happening
Because if we look at the t65, we wrap the whole application with the queric lien provider, and we should also do this
inside our test component. So I'm going to create
a function that gives us let us wrap this inside the query
client provider. And for the clin, let
us just use this. And now we need to
create a client. Because I want to run
this test multiple times, let us create a function
that gives us a test client. So I will call it guest test, test let us call
it G query client. And inside that, we are going to use TansaqerNw core client. And for this, I'm going
to call this function. This will return
as a new object, which is the query client
and I have wrapped it inside I have my list component inside
the query cline provided. I will also specify
an option here. Tan SA query has a parameter
which is called retroy. And this is a really
helpful feature that if your API doesn't return a
response for the first time, TNA query tries to
run the API call, and by default, it does
it for three times. And if at the third time, the response will be get from the API then it
will show you the response. And because now we are testing
and we are not actually interested in the API and we are not testing it with
the real data, I will disable this option
to make our test faster. So I will go and I will
set default option. And here I have a query scheme, and inside this, I will
set the retry fast. And what does this
option do is actually, it says to rea query that if the first time it
has been failed, then you don't need to retry. So now let us run our
test again, and perfect. Now our test is failed. Let us make sure that I am actually testing
the correct thing. So let us add another G here. Now this time the test
should fail and good. And now I am sure that actually my test is running and it does the test that I actually
test what I like to do. Let us run here the coverage and let us see
our code coverage report. And you will see that we need another dependency for
the code coverage. Previously, we were using by
default it was providing. In the next video, I'm going to configure coverage V
eight for wettest.
22. 22 adding code coverage report with v8: So to solve this issue, we need to add the
dependency of the V eight for the coverage tool. So I will install it
with this command, R D. And this will be
a depth dependency, so I will use just D.
And the package will be test coverage V eight. And after that, we are going to our t dot cofi TS file
and inside the test, we will add a section
for the coverage. And we are saying that our coverage for
wider tools will be Vt. And let us return back to our test and
let us run it with coverage. And now you will see that I
don't see that error anymore. If you are not using
web store and you want to have a command to
run the coverage, we can also add that to
our package the JSON file. I can call this
test with coverage. And then here after we test run, I will also give
option for coverage. And in this way,
I can run inside my terminal, R test coverage. And it will run
all of the tests, and it also calculates the
code coverage for one of them. So the app Dot file is failing. Let us delete this test
for now to make it clean. So let's just run. The
test, again, amazing. Both of my tests have been run, and now we can also
get the coverage. Let us go and see
the coverage report. We have the coverage folder, and if I here, I will run
the index dot HTML five. I will see this
inside my SRC to do. For the loading, we
have 100% coverage, but for the list,
we have only 35. And as you can see, this one X shows that these lines of code have been executed
during my testing, but these red lines
have not been executed. And this is exactly because we only added a test for this line. So let us go and add a test for the remaining
lines of codes.
23. 23 increasing list component code coverage to 100 percent: So to write a test, I'm going to actually
copy the whole section, and I'm going to add
a test and I here renders table with
data from the APA, with two do from the APA. And in order to actually test, because first let us
also this part of the code is similar. So let us create a setup here and let us put everything here. Um, instead of this, let us just call setup. And let us make sure that until now I didn't
break anything, so let us run the whole
block and it works. Now, we want to add the
test for the table, and here we need to actually
mock the exxus API call. Because we don't want
to run our back end this will be some part of the unit testing and
integration testing. Here I can do that by dot Mg
and then I will use this as exxus and let us
import from test and now we will define a
variable as a marked axius. Dot Mg will tell that
inside the testing, we don't want to use AXS itself, but we want to use axius a marked version of
the axious that allows us to manipulate the data
that it is receiving. I will map it as
that MkedFunction. And because we are
using TypeScript, so I'm going to cast
this to this function, which I can tell that whenever
axis has been called, I don't want it to be
actually called the API, I want specific
data to be written. To do that, I will come
here and I would say mark axis dot Mark
Implementation. Okay. I can also
use resolve value. And I want to tell
Axios that always, if you have been called, please return a promise to me that will be
resolved to a value. And what value I am expecting
because I'm going to read an object which
has a data key, and this will be
a list of to do. Which are we are returning. I will define an object
which has a data, and this data will be
an array of the to do. I will define one
sample to do here, for example, Cs to do, which will be a to do type, and I will define this as ID
would be one, for example, title will be to do
and is important, false and has done also false. And with this line, I'm telling that every time that
the s has been called, please don't call the API, just give me a promise that will be resolved
to this value. And after that, I am sure that this line when the loading
has been finished, I can bypass this I
and I have an array, and I can show this. Let us run this test, and I'm expecting
it to be failed. Sorry. Okay, it is
still on the loading. So let us go and let us
change this that actually we expecting the description
to be inside the document. And here I'm expecting
it to failing because the first time that
when we run the component, it will be it doesn't it
is in the loading state. And there is a helper function
in react testing library, wait for that we can wait
until something happens. And how we can make sure that
we have bypass this link, if the table is rendering, then I am sure that
this has been done. So if I wait for the description to be
existed inside the document, I'm sure that the
loading has been set to false and this code is
actually executing. So I will put this line as a condition inside my wait for. And I will tell that I want to wait until this description
is inside the text. And when this happened, because I am telling that
I am returning a todo, I'm expecting the ID title
to be inside the document. So I am expecting the
ID of the one and also the title of the todo
to be inside the document. So let us run this test and let us I also should add an Avate here to make sure that this will wait
until this will happen. And because I added
evate I need to change this test to
be an ASN function. So let us test it
again and perfect. Now my test is passing. And what does this do? Actually, it waits until this description will
existed inside the document, and then we are sure that
this and if I change this, for example, to do example, let us make sure that we are
testing something correctly. So now you will see
that it is failing. It renders a table. ID is here, but the
text is to do example. So I can change this, and
now the test is passing. Let us run the post
tests together. And we will also see
warning here that each list should
have a key property. Let us also fix this. This is a This is the react that expects because we know that
the ID is unique, let us as let us add a key property and let
us make this unique. Let us read run the test. Cool. Now, both of the
tests are passing. Let us run the coverage report and let us see the
code coverage report. I'm going to replace all of
the previous coverage tool and let us refresh this
fig and wonderful. Now we also have 100%
code coverage and these lines of the
code that previously read now is getting executed.