Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
Now, with all of that,
the base application is finished
at least regarding the routing functionality.
Now what's missing is actual data for the quotes
and or for the comments.
And that's what I wanna focus on
for the rest of this module.
We're not going to learn about new React router features,
but we are going to learn how we can fetch data
and send data in a React application that uses React router.
And therefore let's dive right in.
Now attached you'll find a sip file, which you can extract,
which holds two folders: a hooks and a lib folder,
and you should add those folders side by side,
to your components and pages folders.
Now the hooks folder holds a custom HTTP hook,
which I just built here for you
since we learned about custom hooks and use reducer,
which I use in there before in this course,
and hence I wanna save some time here
and really focus on the routing part.
And the API JS file in the lib folder,
that's simply holds some functions that will send requests
to Firebase, which I will again use as a dummy backend.
Here you just need to insert your own Firebase URL
because mine which is in here at the moment,
won't work for you because I will have taken down
my Firebase project when you're viewing this.
So here, just as we did it earlier in the course,
you need to go to Firebase and log in there,
and then there simply create a new project.
If this is all brand new, definitely check out
the HTTP course section first, create a new project in here,
and then they are make sure
you activate the real-time database there,
create a new real time database in test mode
when you're creating it,
and then use this URL here as your Firebase domain.
Make sure you delete that trailing slash at the end though.
And with that, you'll be able to use these functions
to send requests and use them in conjunction
with this custom HTTP hook
to reuse certain functionality across components.
Again, these are all things we covered earlier
in the course already and it's not route specific at all.
Now we can get started in the new quote page
because we will be able to see some quotes
if we're able to add quotes,
hence here in the new quote page in add quote handler,
I wanna make sure that we actually do send our request
to add a new quote.
And for this, we can import the use HTTP hook,
which I provided to you from the hooks folder,
and call that hook here.
Whoops, use HTTP inside of that new quote component.
Now this hook works such that it wants a function
that can be called by this hook to send the actual request,
and that will be one of the functions to find in API JS.
These are different functions
for sending different kinds of requests to Firebase.
Then this hook also wants to know whether it should start
in loading state or not, which can be helpful
if we work on a component that sends a request right away,
and then this custom hook will return a function
which became call to actually start sending that request,
and some HTTP state, which actually is an object
with the current status of the request
if it's on its way, if it succeeded, or if it failed,
with the response state off the request
and maybe some error data.
And hence here in the new quote component
when I call use HTTP,
I wanna actually import a function for sending the request
which we get from this lip folder and there the API file.
And here it's the add quote function.
Now, if we have a look at this function, add quote,
it's this function here,
a function where I send a post request to Firebase,
to a quotes node, where I simply add the quote data
and sent this and store this in Firebase.
And then we've got some error handling
and data extraction code down there and that's it.
So now in new quote JS,
it's this add quote function which I pass to use HTTP.
However, we just point at this function,
we don't execute it here.
It's this custom hook
which will internally execute this function.
And then this hook returns an object,
and hence we can use object de-structuring to get some data
out of this object.
For example, to send request function,
which this hook we'll return,
which is and actually the function
we have to call to start sending this request,
and the status of this request.
We could extract more data
but that's all the data we need here.
And then here in add quote handler,
we can call send request, and pass the quote data to it.
And that will then actually send this add quote request.
Now I then wanna navigate a way
once we're done sending this request,
and therefore I will actually also import another hook
from React, the use effect hook from React itself
so that we can define a side effect here,
a side effect function,
which should be triggered whenever the status changes.
And here, I then want to check
if the status is equal to completed,
which is one possible value
I'm setting here in my custom hook.
I'm setting the status to completed
if we have a success or an error response.
And here I wanna check if the status is completed,
in which case I wanna navigate a way.
We could also check if we do have an error
and only navigate if we don't have an error,
but to keep things a bit simpler here,
I'll not add this extra check.
Instead, here I then navigate away with this history object
by pushing or replacing,
depending on whether you want to allow
the user to come back or not,
to /quotes.
And since I'm using history in here,
that's not also a dependency of this affect function,
but history, this history object won't actually change.
Still we should add it to this array of dependencies.
With that, we navigate a way
as soon as the request completed and I don't push here
in add quote handler.
Now we can also use the status to set
the is loading prop on the quote form,
and set this to true if status is equal to pending,
which is another status value set in the custom hook.
The quote form has this is loading prop
which is used to render some loading spinner.
And with this, if I now go back here,
if I now go back to add quote,
and I start adding this, if I click Add quote,
we see the loading spinner and then we're redirected.
And on Firebase, we now have to quotes note
with a newly added quote.
Now of course we wanna fetch our actual quotes
and display them here on the quote list component
instead of using the dummy quotes.
Therefore on this all quotes page
I now also wanna send the request.
So here, we can also import use HTTP
from our custom hook here,
and also import one of the functions from the API file.
So from lib API.
And here to function which I want to use,
is the get all quotes function.
Now this function will in the end
just well, do what the name implies.
It gets all the quotes and then just transforms them
into an array which we can use.
Now in the all quotes component function,
we can therefore call our custom hook,
and pass a pointer at get all quotes to it.
Also sets true here as a second argument,
that controls that we start in loading state
and that therefore a status is pending
right from the start.
And then we can extract some data here.
And here we can get the send request function
to actually send the request,
we can get the status, we can get the data,
and I will assign an alias here,
loaded quotes.
So that's the actually the constant name
by which we can access the loaded data.
And we get an error maybe.
That's now how we can use this custom hook.
And now we need to use the use effect hook
to actually send that request when that component loads.
So from React I import use effect here.
And then here we can call, use effect
trigger a function,
and simply call send request here.
And therefore send request is now a dependency
we should add here like this.
So now we will send the request
whenever this component renders in the end.
Now we can handle the different states
and check if the status is equal to pending,
so if we're still loading,
then we can return a div with a class name off centered
and in the output the loading spinner,
which is a component you can import from components,
UI loading spinner.
And that will then show such a loading spinner
whenever we are waiting for the quotes.
We can check if we have an error
so we made it past this loading check,
but now we check if we have an error maybe.
And if that's the case,
I'll return a paragraph with a class name off
centered and focused.
Again, these are global classes defined here
in this index CSS file.
And then I will just output error here,
which will be the actual error message.
And thereafter I'll check if we maybe are not loading,
and we don't have an error, but maybe we have no quotes.
And therefore here I'll check if the status is completed,
but we also have no loaded quotes
or loaded quotes has a length of C rows
so we will have an empty array.
And if even that is the case,
and we're done sending the request,
then I wanna return to no quotes found component,
which is a component I already defined for you here.
And that's therefore a component
which we need to import here,
the no quotes found component from components,
quotes, no quotes found.
So I'll then output that component.
And if we make it past all these checks
then we know we don't have an error,
we're not loading, and we do have quotes,
and then I wanna output my loaded quotes here
instead of the dummy quotes.
And that means that now we can also get rid
of this dummy quotes array.
And with that, if I reload,
we see the loading spinner briefly,
and then we see the quotes. If I clear that quote here,
if I delete it,
on Firebase, then we have the no quote found text
and this Add a quote button
which at the moment doesn't work though.
Because and is no quotes found component
there I'm outputting a regular anchor tag.
And this should actually be a link to this new quote page.
And since it should be a link,
I don't wanna use an anchor tag, but as we learned it,
used the link component
from React router dom.
And then here we add link
and set to to prop to new quote.
So to does path, which that loads us
this new quote component.
And with that we can click this link
and we're taken to this forum.
And now I can again add that and we display it here.
Now we all wanna fetch the quote data
on that quote detail page of course.
And for that we can go to that quote detail page.
Here on that quote detail page
we also wanna use the custom HTTP hook.
So we import that from hooks use HTTP.
And from that API file, I also wanna import a function
which will send the actual request,
here it start get single quote function.
And then in the quote detail component
we wanna call our custom hook,
and pass a pointer at that gets single quote function to it.
Also start in loading mode
and therefore past true as a second argument,
and then use object de-structuring
to use the data returned by the hook.
Here we still get the send request function,
the status of the request, some data which all LES
to loaded quote and maybe an error.
Now we will no longer get to selected quote like this
because we will no longer use the dummy quotes here.
Instead, we wanna send the request when this component loads
and therefore again, I'll import use effect from React,
and then call it here and define a function
that should be called, when this component loads.
And here we call, send request.
And we therefor add send request as a dependency.
Now the important thing to note though,
is that the get single quote function
wants to quote ID as an argument
because it needs to know for which quote ID
it should fetch the data.
Therefore we actually need to pass that ID here
to send request.
But getting that ID isn't too difficult
because we got access to our parents here.
So we can get our vote ID out of the parents
with object de-structuring
so that we can pass quote ID as argument here.
And now we also need to add it to this dependencies array,
and that's also why I'm using object de-structuring here
because that allows me to just pass to quote ID
as a dependency instead of the entire parents object,
which would mean that whenever any parameter changes
this effect would rerun.
Here we only have one parameter but still,
if we potentially had more
we could rerun this effect unexpectedly
and therefore using object de-structuring
to be as precise as possible is definitely a good idea.
So now with that, we're sending a request
to get a single quote.
Now we can again check our different states here.
We can check if the status is equal to,
pending, so we're loading, we're waiting for the response,
and then I'll return a div for the class name off
centered again, in which output
this loading spinner a component,
which we again have to import of course
from the UI folder in the components folder.
And if we made it past this check
and we know that we're no longer loading,
I wanna check if we may be having an error,
in which case I want to return a paragraph
with a class name of centered,
where I output that error message.
And I also wanna handle the case
if you maybe didn't find a quote.
So I will check if we not have a loaded quote,
which is the actual quote data returned by this custom hook,
in which case I say no quote found.
But if we do have a quote, then I wanna use that
and I'll use the load of quote down there
to output my quote data.
So with that, I'm able to load this quote.
One thing I just wanna fine-tune
here I actually wanna check
note if I don't have a loaded quote,
because of the way this get single quote function works
I'll always have a quote object.
But instead I will just check if the loaded quote
maybe doesn't have a text.
So if that is undefined or falsey.
That's the better check
for checking if we don't have a quote.
And now with that we're offloading the quote detailed data.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.