So how can we fetch posts
when we first visit or reload this page?
Well, for that, you could, of course,
say that you go to PostsList
because that's where we need the posts.
And we also send a fetch request here.
We target the same URL as before
because if we take a look at the backend,
we see that in the end,
a get request to /posts gives us all our posts.
And then here, we already send a get request
because as mentioned, that's the default
for the fetch function
so we don't need to configure this request.
And now what?
Well, now in the end, I wanna make sure
that we update our posts here
whenever we got a response.
Well, for that, you could try to use async await like this
but this is not really supported.
Your component functions must return JSX code
or some other values
but promises should not be returned,
at least for this standard component here
without using any extra framework on top of React
or anything like that.
So promises may not be returned
and since adding async in front of a function
always ensures that this function returns a promise
because any data returned by the function gets wrapped
into a promise, we must not use async here
and we therefore can't use await here.
But of course, we could use the standard old school way
of handling the response,
and add the then method here
to get our response
and then return response.json to unpack the data
from the response
because that's how you do it with this response.
There is a JSON method,
which then ultimately gives you the data
that was sent back from the server.
And that data that's sent back is an object
with a posts key that holds all the fetched posts.
So we could add another then block here
and then access data.posts,
and there to be precise,
we might want to call setPosts
and set our posts to data.posts.
But we should not do that.
You should not save that, you should not write this code
because if you would write this code,
it theoretically would update the state
with the new posts but it would cause an infinite loop,
and why would it do that?
Well, simply because whenever you update your state,
as you learned, your component function
gets executed again by React.
That's one of the key ideas of React
that updating the state causes the component function
to be executed again,
so that React can update the UI if needed.
However, if this component function executes again,
this fetch request also gets sent again.
So we sent another request, we get data,
we update the state and the loop begins again.
So this is not code we wanna write like that.
It would cause an infinite loop.
So therefore, since that's not the solution
for fetching the posts, how should we do it?
Well, this is, of course, a common problem
and therefore, React has a solution.
It has another hook we can use.
Now, the hook we can use to solve problems like this
where we effectively wanna cause a side effect
in our component function,
so where we wanna trigger some action
that does not directly influence the JSX code
but maybe indirectly in the future
or that does anything else
that's not related to rendering the UI.
In such cases, we get another hook we can use
and that would be the useEffect hook,
which is there to wrap side effects.
useEffect allows you to safely run code like this
without causing an infinite loop
but how does it work?
Well, you execute useEffect like this.
And unlike useState, it does then not return a value.
Instead, it takes a function as a value
and as a second argument, an array.
So two arguments that must be passed to useEffect:
a function and an array.
Now, I'll come back to the array in the future.
Let's first focus on the function.
This function will be executed by React
for you whenever it considers this effect
to require execution,
and I'll get back to when it considers this effect
to require execution in just a couple of seconds
but I can tell you that this second argument,
this array has something to do with it.
We can, however, now grab our code
and put it in there
and we could now also actually wrap it
into an extra function.
fetchPosts could be the name,
which is an async function,
which is defined inside of the effect function
so that we can move our code in there
and actually use await to get our response.
And then also get our responseData
by awaiting response.json
so that we have this more readable code.
And then we update our posts
with the resData.posts.
I created this extra function in this effect function,
instead of turning the effect function itself
into an async function
because useEffect takes a function
that should not return a promise itself
but that instead should return nothing
or a cleanup function,
which is not too important for us here,
which I do, of course, cover in my Complete Guide course,
but which we can ignore here.
But we should not return a promise here
for this effect function
and therefore, we should not add async here.
Instead, I create an inner nested function,
which I then simply immediately execute
inside of this effect function.
And this trick allows me to use async await in here.
But back to the effect function itself
and the idea behind it.
As mentioned, React will now decide
when this function gets executed
and therefore, when this function gets executed indirectly.
And I can tell you that now with this setup here,
it will not always get executed
when this component function executes.
Instead, if we save this code,
and we reload the page,
you see that now this post appears magically
and that's, of course, the post from the backend.
And there we can prove this.
If I go to the backend,
and I would edit the body here
in posts.json, and save the updated file,
and I then go back to this app and reload,
you see that was uploaded here as well.
So this data is coming from the backend
thanks to useEffect.
But how exactly is this function working
and why is it now not causing an infinite loop?
This useEffect function here, this hook
is now preventing an infinite loop from occurring
by simply making sure
that this effect function does not always execute
when the component function executes.
It executes sometimes
when the component function executes.
Otherwise we wouldn't have fetched the posts
but not always.
But when does it execute?
Well, that's controlled with this second argument
that's passed to useEffect, this array here.
This array in the end specifies the dependencies
of your effect function.
And a dependency is simply any variable
or function that might be defined outside
of this effect function
anywhere in your React components, in this component
or some parent component passed down through props.
And whenever such a variable or function defined outside
of the effect function changes,
receives a new value, for example,
this effect function will be executed again.
Now, if we have an empty array,
it simply means this function has no dependencies
and therefore, it will never be executed again.
Instead, React will only execute it once
and that's when this component is first rendered.
And technically, it gets executed
after the component first rendered,
so theoretically, the component first renders
without any posts
and then it immediately executes this effect function
where the posts get updated.
But that's all so fast
that we only see the final state here
where the posts are fetched.
But that's how this executes.
And this now gives us fine-grained control
over when this executes.
So that's how we can handle side effects,
like sending HTTP requests.
Again, we, of course, dive deeper
into effects and all these things
in my Complete Guide course
because that's the idea behind that course,
but that's in a nutshell what you must know
about useEffect and how it can help you, for example,
for fetching data when a component is first rendered.