
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
Complete source code available till this point of lesson is available at
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
00:00:02 This useEffect approach that we just implemented is okay, but it feels more like a quick fix than a real solution.
00:00:10 Sure, you could make this view component a bit more meaningful instead of returning a null, but there's a much better way than simply creating a new component
00:00:19 and importing it at the top of the page.
00:00:21 Instead of calling a useEffect through a separate component, we can make a server call directly after we get the question details page.
00:00:29 And we can do it on the same page.
00:00:30 So first, let's delete this view component as we will no longer need it.
00:00:35 And let's modify the question details page to implement a server-side call.
00:00:40 First, I will remove this import from the view component and its render right here.
00:00:46 And next, right above this redirect 404, I'll simply call the server action by saying await, increment views coming from question actions,
00:00:58 to which I'll pass a question ID equal to ID.
00:01:01 Let's see if that works.
00:01:03 Currently, this data renderer question has 11 views.
00:01:06 So if I click on it, it still seems to have only 11. But what if I reload?
00:01:12 Oh, it's 12 now.
00:01:13 13, 14, 15. Okay, so it works, but only after a reload.
00:01:18 And you might be okay with that.
00:01:20 But there are some use cases where you want to show the change immediately on the UI, rather than have to refresh or head back to home and then come back
00:01:29 to this page.
00:01:30 This is happening because we're making a server call.
00:01:33 So when a user requests this question details page, it first gets the contents of the entire question details page, It then increases the view count and
00:01:43 then displays the result on the UI.
00:01:45 But what about the revalidated path?
00:01:47 Remember, we implemented it right here within this question action.
00:01:50 So why is it not updating the data or invalidating the cache data?
00:01:55 Again, it's because we're making both calls on the server side.
00:01:58 We're not invoking anything on the client side, so the server can revalidate its data through revalidated path.
00:02:05 once these calls are made, only after the data is rendered.
00:02:08 That's why it doesn't matter if we have a revalidated path or not, as everything is happening on the server side.
00:02:14 So, let's simply remove this revalidated path from here, as it's not really doing anything.
00:02:19 So, what's the solution?
00:02:20 How can we see the views reflected automatically without reloading the page, similar to what we had previously with the use effect?
00:02:27 How can we achieve the same thing here, but with server calls instead of client-side calls?
00:02:32 Think hard.
00:02:33 If you think about it, you'll notice that we're calling increment views right after calling the get question server action.
00:02:40 Let's reverse that and see what happens.
00:02:42 I'll put the increment views above and only then will we get the question.
00:02:47 If you save it and reload.
00:02:49 Oh wait, it's 19. Let's go back to home just to check it.
00:02:53 We are at 19 right now.
00:02:55 So when we click on it, it should be 20. Oh, and it is 20. Reload 21. So it's actually working immediately as soon as we click on this page.
00:03:06 This one has zero views.
00:03:08 So if I click on it, now it's at one.
00:03:11 Perfect.
00:03:12 It works in an exact way that we want it.
00:03:14 And while that is nice and I don't want to rain on your parade, there is an issue with this approach as well.
00:03:21 The issue is that the user has to wait for these calls to be executed before showing anything on the UI.
00:03:28 So first we have the server call to increment the views, which let's be honest has nothing to do with rendering the page.
00:03:34 Then we have to get the question details because we need it to be able to render it.
00:03:39 And only then do we render the necessary UI.
00:03:42 That's a lot of UI blocking, which causes a famous issue called the waterfall effect.
00:03:48 If you head over to the network tab and click fetch XHR and reload, you can also clear it and then start recording from scratch and click it right here.
00:03:56 And you'll see this waterfall happening right here.
00:03:59 It's called a waterfall because we have one request, then another, and another, and another.
00:04:05 And you can see how many of them are happening one after another.
00:04:08 Obviously, something here is not good.
00:04:10 If you head over to performance, you'll notice that right now we have a very nice, largest Contentful paint.
00:04:15 Less than a second.
00:04:16 But what happens is, if you increase the number of requests being made to the server, the waterfall effect will increase,
00:04:24 and it'll end up hurting both the largest Contentful Paint and the first Contentful Paint even more.
00:04:30 So the question is, how can we get a proper first Contentful Paint?
00:04:34 Or in simple words, how can we get the content rendered in front of the user as soon as possible?
00:04:40 Well, actually, there are a couple of ways, and I'll show them to you right now.
00:04:45 Keep in mind that this is not necessarily about improving this little 200 millisecond delay while trying to increment the views.
00:04:52 It's about teaching you the underlying concepts of how Next.js works, how server calls are being made, and how the UI gets rendered in front of the user.
00:05:00 One way in which we can improve the performance of our application is by implementing something known as parallel requests.
00:05:08 Because right now, the requests we are making are sequential, which means that they will happen one after another in a sequence.
00:05:17 But if we introduce parallel requests, we can improve performance.
00:05:21 As you can see from this graphic, sequential requests result in a waterfall, introducing the total time for all the requests,
00:05:28 whereas parallel requests happen at the same time, reducing the total time it takes to load something or render the UI.
00:05:35 They are eagerly initiated and will load data at the same time, reducing the total time it takes to load data.
00:05:42 So, how do we implement them?
00:05:44 Well, it's pretty simple actually.
00:05:45 You just have to wrap your calls in something known as Promise That All.
00:05:50 It looks like this.
00:05:51 Const.
00:05:53 Destructure the results.
00:05:54 First, you can get the result of the increment views.
00:05:58 And then you can get the results of the question.
00:06:00 It looks like this.
00:06:02 Const.
00:06:03 We get back something.
00:06:05 We'll see what that something is very soon.
00:06:07 But then you call and await Promise That All.
00:06:13 and then you pass an array into it.
00:06:15 Within the array, you can call both of these server actions.
00:06:20 First, we're going to call increment views, so let's just simply paste it here, and then we can separate it by a comma, and then simply call the await
00:06:30 get question.
00:06:30 It even looks nicer and makes more sense if you do it that way.
00:06:33 But how are we going to get access to the output of the data of the second call within the list?
00:06:39 Well, here you can destructure different responses.
00:06:43 So first we get response one, that's the response from the increment views, and then you get the response two.
00:06:50 When you don't need to use the response one, in this case, increment views is not actually returning anything, you can just put an underscore there,
00:06:57 indicating that we're not planning on using that variable.
00:06:59 And for the second one, we can just destructure the same thing we had before right here.
00:07:05 And that's it.
00:07:05 We have replaced two calls with a single one that happens in parallel.
00:07:09 And keep in mind, you can only do parallel requests if one request doesn't depend on the other.
00:07:15 For example, if we didn't have the ID of the question peer before, and if you had to fetch that ID by calling the getQuestions,
00:07:23 then you would need to call these sequentially to get the ID to then be able to increment the views of that question.
00:07:30 But in this case, they're not depending on each other and we're totally okay to do this.
00:07:34 So if you go ahead and test it out, currently we have about 24 views and if you click on it, we get 25. It works as expected,
00:07:43 but sometimes it actually might not.
00:07:45 26, 27, 28, 29, it's actually good.
00:07:51 But unfortunately, we can't have a guarantee that incrementViews will be executed before getQuestions.
00:07:58 Because even though it's first on the list right here, that doesn't really matter.
00:08:01 It'll try to make both of these calls at the same time.
00:08:04 In this case, it just works out well for us because incrementViews most likely takes less time to happen, so therefore it does it first.
00:08:11 So while parallel data fetching enhances performance by starting multiple data requests simultaneously, avoiding that waterfall effect of sequential requests,
00:08:21 it can still lead to challenges like slower requests, blocking rendering, increased server load, error handling complexity,
00:08:28 or race conditions.
00:08:30 So these are definitely interesting topics to explore.
00:08:33 But for now, this solves our problem pretty well.
00:08:35 But keep in mind that with this approach, we still have to wait for the views to be incremented and fetched to be able to show the rest of the content
00:08:44 that doesn't necessarily depend on the views.
00:08:46 If only there was a way of fetching absolutely everything regarding the question details before incrementing the amount of views and then only doing it
00:08:56 later without blocking the UI.
00:08:59 Hmm, that would be amazing.