So before we conclude all of that here and you can always dive into the github repository to learn more,
let me show you one super important feature of nextJS,
let's go back to the index.js file in the pages folder, so our main page here
and let's turn this from a functional into a class based component by naming this class IndexPage
maybe, exporting this as a default,
let's them therefore also export component from react because we still as always need to extend component
here
and there we have a render method, so this is all just the same
where we return some jsx and the jsx of course is the jsx I returned before. Let's get rid of
that stuff down there, quickly reformat and we're good to go,
everything should still work as before.
Now we're using a class based component and that's one thing I wanted to show you,
I also want to show you a special lifecycle hook you can use though
and unlike the react lifecycle hooks, that lifecycle hook would even be available in functional components.
I'll show you how to use it there
too but let's start in the class based one.
It's called getInitialProps and it will receive an argument which describes the context of your application,
let's simply log context to see what's inside of that
when this gets called.
Now to see what's inside of that, we need to change it because it's not a normal lifecycle method
like the other ones, instead it's a static method which means it can be called without the component being
instantiated yet and it's an asynchronous method which means it doesn't resolve, it doesn't return something
instantly.
Now let's save this and wait for a compilation and let's reload the page then,
now we see that it should resolve to an object.
So let's fine tune it and let's make sure we actually return an object,
it can be empty though.
And now with that, let's reload the page and we don't see anything here, we don't even see a console log.
We can see something in a console though, in the console here where we ran npm run dev because this
code actually is executed on the server first, it will only be executed on the child if you navigated
there within the app
so by clicking a link for example. If you navigated there by typing the URL and hitting enter or refresh,
it executes on the server,
that's the special thing about this lifecycle method.
It executes either on the server or the client and you can use it to initialize your app before it loads,
so on the server for example in getInitialProps, you could fetch data from a database and then pre-
populate the props this page component will receive with props of your choice.
For example here we could hard code the app name prop which is a super app which of course here isn't
fetched from some database but you could easily do that since it's an async method, you can use await
keyword in here to await for a promised resolve and you would typically have a promise or something
like get if you are reaching out to a web server,
for example with axios.
Now if you don't want to use async here, what you can also do is you can still use normal static method
like this in case you don't know that async await syntax
and then what you would do here is you would create a promise or use a package like axios which does something
that turns a promise, here I'll create one manually with the new promise keyword and there, if you create
it manually on your own, you would always pass a function which receives resolve and reject, two functions
that can execute.
If that's all new to you, I recommend refreshing the promise knowledge in general as this is an important
javascript feature.
In a promise, you typically execute async code and again often times, you don't write promises on your
own but you use some package which wraps some async action like reaching out to a server in a promise,
axios which we used in this course does that for example.
So here in that async action like setTimeout to fake, the reaching out to a server, you would then call
resolve and return your data like the name of the app, Super App. And then what you can do
or let's name it app name here
too. What you can do is you can listen to that promise with the then keyword and pass a function to then
which will be executed as soon as the promise resolved.
Now this then part is what we leave out here,
instead here we simply return the entire promise in our getInitialProps method and nextJS will
take care about listening to its result and then pre-populate our props once the result is there
and only render the page once the result is there.
So now here in our page, we could say the main page auth and then render this props app name and we
know that this will be populated because we pre-populate the props here in our getInitialProps function.
If we now save this file here and we reload this page,
you'll see it takes a bit longer to load because it needs to wait for this second
here, we specified that on setTimeout but then it actually displays Super App here because it did pre-populate
our props. So getInitialProps,
super important working together with promises, either promises written by you or returned by third party
packages,
it'll wait for them to resolve and pre-populate your props.
Now let's dive into that context we get here,
we print it here with console log and we can inspect it here on the server since we loaded the page by
simply refreshing it.
Now it's quite hard to read that here because we see all the nested properties and so on too,
so let's get rid of that and instead have a look at the official docs of nextJS.
There if we go to the getInitialProps part which is about fetching data and the component
lifecycle,
we see that the context has the path name of the page we loaded so what's after the slash, any query params
we might have and important on the server only though, the request and response object.
So basically the same you would get in an expressJS environment,
this allows you to really get all the information all the requests that reach the page.
You might not need that but there are also some use cases where this can be really helpful as it allows
you to analyze what exactly the user requested and so on.
So here we're not taking advantage of the incoming context data,
we could do so though, of course we're nonetheless using this to initialize our props which is an important
function of this method,
it's probably the reason why it's called getInitialProps.
Now how do we use this in a functional component?
This is possible,
you can see how it works on the official documentation too, you simply create your constant and then add
this as it is a static method to that constant after you created it. A function which a functional component
of course is in the end allows you to add something to it inside of that function, a function which this
constant here in the end is and which our constant here also is is just a javascript object so we can
add static methods to it.
So I can just say authIndexPage.getInitialProps and therefore I define this method and nextJS
will only call it if it is defined
otherwise it will just skip it and then we define it just as we did in the other file.
So there, I can also set up my promise here and then return it and set getInitialProps equal to an
arrow function where I would receive context passed in automatically by nextJS and then create
my promise and return it.
And here we can say app names Super App Auth to really see that something's different and here, we could output
is in our jsx code of course
too, app name. If we now save this,
we see that if we reload our main page not /auth, it of course still works but if it go to auth, it
takes a second because it needed to resolve that and then it just fails because I forgot to pass props
into that functional component.
We have to do that of course,
so let's try this again,
let's go back to the main page first and then let's click on auth and wait that second
and then we go there and also see that populated.
So getInitialProps,
super useful lifecycle which works in both functional and class based components and which allows you
to initialize your props before the page is actually loaded.