As always ,you are awesome Jack, you keep digging here and there and come out with something incredible like this , and I see the beard coming ,cheers man and tell the wife to let the beard grow
jack you absolutely rule! so much of your content helps me at work and quite often; whether its brainstorming, understanding new concepts, or an idea of a new direction to look into. thanks so much and keep it up man!
Thank you infinitely for the efoort and the knowledge you are spreading with us. May i forward my question or a request let's say... What is the best way to connecr nextjs and a separate backend in term of forming our logic, there are actually ways for example request direct from components or using api routes as a proxy
Thank you so much for explaining this Jack! When passing promises as props, does it mean the 'promise cracking' phrase is happening in React hydration stage? Does it also mean it might affect the CLS if I do not have the right size (dimensions) for a loading component as fallback? Thank you so much again for these awesome video!
`use` is cracking the promise and most likely throwing the promise on render and then React is getting that promise and subscribing to it itself so that when it resolves it will re-render the component. And all that is done on the server side. If you look at the RSC payload you can see a "promise type" marker with the data from the promise, so it's resolved on the server. Then on the client during hydation they use do a Promise.resolve(payload) and pass that in.
@@jherr Hi Jack, Thank you for explaining how the promise works both is RSC and client component! If everything rendered on the server side, would it be the same as SSR in page route and the page load should be fast? I thought I would not even see the loading stage when the html is ready to be served. However when I tried your example with image fetch instead, I would see a loading state before image loaded, rather than seeing the image right away (comparing to page route approach). Does it mean it is slow even when the promise gets resolved on the server?
@@afion113 So if you are going to get the image data on the server, and that image API is slow, then ask yourself, would you rather the customer have an interactive page with a spinner, or a page that is slow to respond? Because the App Router gives you the ability to have a fully interactive page where parts of it stream and become interactive. Where the pages router simply blocks on getServerSideProps which means that the page would simply be slow to repond.
Awesome video. I actually use RTK and RTK query for my projects and hoping to move them into NextJs. Request: Please Can you make a video on using RTK with Next JS . I will be grateful.
Pro tip: when creating files in VSCode you can write the file path. Vs code will automatically create all folders to that file. Found that feature wery useful when defining routes in app router 🙂
Don't you still feel we are introducing many anti patterns for server side components here? 1.Creating a api endpoint for fetch that should be done in the server component not an own api 2.Talking about React Query and such that becomes more obsolete with server side fetching and caching. 3.Using boundary package. The thing for me is that I have not come to face this kind of problem, maybe I will, but still this feels too complex.
Hi Jack! Do you have any references for understanding how client components that receive props from server components are rendered? It’s confusing to me that a client component that receives props from a server component would actually be server-rendered and “blocked” by the fetching in the server component, as you mentioned. What parts of such a client component are actually client-rendered then? Thanks!
The actual blocking in the "client" component happens on the server side, the rendered component is sent to the client when the server render of the client component is completed. "Client" components are rendered on both the client and the server.
@@jherr In that case, is there a way to render a loading state in place of the client component while the server component is performing the data fetching? Should I use a loading.tsx? Thank you so much!
@@DesolationPhoenix Yeah, if you use the `use` hook then wrap it in a Suspense as shown in the video. If you use the React-Query `useQuery` hook then look at the `isFetching` boolean and render a loading state if it's true (again, as shown in the video.)
That question was in my head the whole time while watching the video 😅 Honestly, the way that is handled with rsc is next level. That's so much more convenient. Btw. are the any good reasons for using react query etc over use + suspense?
If you're scaffolding to use app router but grab the football and instead pass the promise to a client component, why not just have the client component fetch with React Query to begin with?
Hi, Jack. I enjoyed this video a lot! I have one question though. In the documentation of react-error-boundary, the author says it can only be used in a client component. Why does it works fine in a server component in this case?
great video 🙌 I do not understand why we had multiple copy of the data in vdom part 4:47 . what is the cause of this? data is already at page level and in one place. 😕
Anything you pass to a client component as a property is serialized and serialized independently of any other component. That's why the multiple copies. The context is a single copy because we are only sending the prop to the provider client component and then it's sharing it around both on the server and on the client.
thanks for the answer 🙌 I believe some kind of lint rule is needed to avoid this. It is a mistake that a developer can easily make and it can realy hurt the perf. was it like this before app router?
Interested in the app Router nextjs course. I am just hoping there is purchase power parity, brazillian real is super weak and my Jr salary doesn't go very far
Hello Jack thank you for your awesome videos. I wanted to ask you a question that I’m struggling for a while. I have two projects one is a nextjs project of a website and the second one is a monorepo project that contains reusable components. These components are published to npmjs and are imported as dependency into the first one. The issue is in the development workflow. I’m trying to link with pnpm link the components packages to ease the workflow and it works but if you have any hook for example useState in any component it will throw an error saying can not read useState of undefined. Thank you
You probably have competing React versions. So the components are on one version of React and the NextJS server is another. Is this 13? If so you want 18 across the board and probably more specific than that. FWIW, the best solve here is to bring everything into the monorepo.
@@jherr yes very good point and I checked it all projects are of the same version of react and common dependencies. You can easily test it by recreating two new projects from scratch (we tested it too). One strange thing is that when we where using nextjs 12 this issue was not present after upgrading it to 13 it appeared. I might be wrong but I think it is related to new transpile option in nextjs 13. Before we were using the withTM module.
great video! thank you! somehow, after i change to use ReactQuery, the html in the client side component doesn't show up in the html dom. any idea what i might do wrong?
I would be interested to see you make a video exploring Livewire 3. I don't think it gets enough attention from the tech community here on RUclips considering what it's capable of doing.
Next js 13 loading hooks very slow when page loaded then its loading hooks and javascript example my sidebar loaded its need hooks to works it take 2s to load hooks when page full loaded my web app look like its lagging
Great video, I am not sure how React query is able to stream HTML for loading indicator first and then foods later without using Suspense. I thought Suspense is the only mechanism to tell React that a certain part of the application is waiting for data.
Does this mean the loading indicator for RQ is replaced with foods by client side bundle. It is not same rendering pattern as React streaming using Suspense ?@@rokonzamann
@@rokonzamann have a look at what’s coming out of the server. It’s holding the connection open then sending more HTML and JS as the streams are resolved. That’s not initiated by the client.
Will react-query still re-fetch on invalidation in this example? Is it aware of how to make the fetch happen again if it is passed as a prop from server component?
Hey love the videos and ive been subbed for a while. Could you please make a video regarding csrf protection in the new app router dir. There seems to be no packages for the new update and there really isn't many videos covering how to create your own either.
I'm not sure I understand the benefit of react server components if you're doing promises for props. Like what's even the point then? Seems like you're running in circle by doing this whole shazam, using tanstack query on the frontend would've provided the exact same benefit
A big benefit is that you are making the request off the server. So you get better security and performance. In addition if you need SEO then there is a big benefit to rendering on the server because the HTML is generated on the server and is easier for the bots to handle.
@@jherr I'm talking about this specific use case in the video (promises for props). Performance would be the same since you wait for the promise to finish. I'm not sure about the security part, what security issues does this prevent that a separate backend wouldn't? The other flow (with tanstack query for example) would be to fetch from the client from a backend server, then that server can fetch the same way it's being done in the video, only less convenient I guess. And I might be wrong on this, but server components don't generate HTML on the server (that's being done by renderToString) but instead send the serialized react tree to the client (so not *directly* html)
@@Andreiu2011 So about whether the API is being called from the server or the client. There are several reasons why it's ideal to call from the server. First, NextJS servers are often deployed in the same VPC as the microservices they call, so it's a much faster connection. Second, the microservices don't need to be deployed to the open Internet because they are being called only by the NextJS servers within the VPC. And third, third party APIs often have access keys which shouldn't be sent to the client for security reasons. So making the requests from the server avoids the key leakage. There are more advantages, but those are some of the primary ones. And "server components don't generate HTML on the server" is pretty easy to test that yourself, just create a NextJS app, start it up and look at the page source in the browser. You will see all the rendered HTML (as well as the VDOM). "View Page Source" shows what comes back from the server, it does not show the current tree. For the current tree you can use the inspector. You can also see the HTML rendered from the server in the Network panel of the inspector as the response to the initial route request. Or you can just curl the server as see what comes back.
My recommendation is to use middleware to inject an API header key into the request header with the prefix for the API. It might be something like `X-API-Base-URL` or something like that, which you can set however you want in the middleware and then the components pick it up with `headers`.
If we don't include "no-cache" then we wouldn't be "awaiting" for the data in all the components and the components would just reuse the same promise. And I reckon if we use context for passing the actual data instead of the promise, it should also send only one copy of the data with the vdom
If you a requesting off the client then yeah, they would all pick up the same cache. But that's not going to SSR, so if you want SSR then you have to request the data in an RSC.
I don't think that's correct. All of the action is happening on the server. So client-side JS or not you would still get the error boundary content (or error.tsx) content coming off the server if there was an error.
@@jherr try to turn off js, you wont get any errors to render. In remix you will. Dan Abramov, explained that there was a missing part for sending errors as an action return. And it’s not implemenred
I took a break from this channel for a bit, I can't believe you're still talking about NextJS payloads, it's seems like every single video. Using context for promises is a decent pattern but not realistic in the long term. And to make use of Suspense with RQ, it has a flag for that. Just using isFetching by itself is a CSR indicator. And not likely what you want if you want that loading state to float up to a larger component.
@@rubendacostaesilva8442 I wouldn't use Zustand or Jotai in their default "global" mode since globals with App Router are a no-no. Instead I would provide Zustand or Jotai atoms via context so that you are guaranteed that the state managers are per-request. Zustand and Jotai totally support this model, it's just not as super-easy as it usually is. For Zustand for example, you first call a hook that gets the Zustand hook from the context, and then you call the Zustand hook just like before.
I only brought in the external library in the error case for simplicity. An error boundary is a single class component that is ~10 lines of code. But yeah, if you just want a catch-all you can do error.tsx.
@@rajeshdavide That's actually pretty complicated because it's both on the client and the server. "client" components run on BOTH the client and the server. That's number one. So when a "client" component on the server that uses `use` gets a fulfilled promise it renders on the SERVER. The HTML and the data are then both sent to the client where the component instance on the client is hydrated symmetrically and the `use` is run there too.
So if that's the case, can I assume that the fullfilled promise is streamed after the client renders the component ? Do you have a material where I can read more ?
Loading and error are great to handle the route level errors. Here I'm demonstrating how to manage errors and suspenses at whatever level of granularity you want within the component tree.
Neat trick but I wonder the benefits, we get no server rendering of data, so doesn't work for no js/crawlers and more complex than an API and use query
What do you mean get no server rendering of data? I showed every time that the data is server rendered. Have a look at the HTML I showed from the page source. That's coming back from the server.
@@jherr I guess not if you disable js, as the promise has the data, and not the html? I guess I can see the value if the API is slow enough you wouldn't want it on initial render maybe
@@griffadev If you look at the output of the server, regardless of whether the client has disabled JavaScript or not, the HTML coming out of the server has all the rendered HTML including the HTML that comes in late off the suspense because the connection is held open until the suspense completes.
@@griffadev No problem. The whole client/server isomorphic thing has always been a little complicate when you look into the details. It was simpler with the Pages Router because the flow between getServerSideProps and then rendering, then sending it to the client, and hydrating and running there, blah blah blah, was pretty straightforward. Now, with RSCs and streaming, things are getting more complicated. They are CONSISTENT, which is cool, but complex.
can't you just use the loading and error components in the app router instead?? (error.tsx and loading.tsx in same level as the route.tsx which is currently server side rendering)
This demonstrates using error boundaries and suspenses within the component to all for a finer level of loading and error indication granularity. If you don't need that then feel free to use error and loading.
@@josevsebastian2909 you can only use them in pages right , it will wrap up the whole page with the error fallback if something fails , but if u r only using that api response in particular component then I think its best to just wrap that piece of code with error boundary
@@yuvarajyuvi9691 in page router it works like that. Wrapping everything in error boundary and suspense. But one of the main advantages of app router is that, it respects the nested layouts of different routes, only the "page" leaf component is replaced by the boundary, all the "layout" is still rendered. And most often that's the result you want, except when you need granular loading or error handling inside the "page" and even that can be done using parallel routes.
I dont think we need to give underscore for the component name, Nextjs is smart enough to not include it as part of the route page as long it doesnt have page file in it, cmiiw
i dont understand why u are using suspense and error boundaries when next has loading.tsx and error.tsx specifically for this. also why use react query here it does not make sense to me. lastly i feel like this is not a common usecase does the next/react team encourage us to do something like this? i feel like situations like this huge payload are fairly uncommon. plz do lemme know cause there is still a lot i need to learn about the app router
error and loading are route level, using suspense gives you the ability to give skeletons/spinners at a component level. the addition of react-query is the basis of a nice pattern of re-fetch and valuable to folks who already use that library (or SWR) to manage promises. it's just further validation that the promises are indeed promises. as for common use case, there are lots of use cases. i've personally worked with very large data sets on both client and server side. the nice thing about the App Router is that we are no longer sending everything out of getServerSideProps to the client, now with RSCs some data can remain strictly on the server and we can limit the amount of data going to the client.
@@jherr would parallel routes be a better alternative to the suspense and error boundry situation? also what do you think of the long term use of something like react query and swr with next now pushing to have mutations with fetch? i had never faced this data issue so far (mostly cause we still use pages at work haha) but will keep this in mind!
@@MrZiyak99 parallel routes are for rendering separate sections of the page like the header/footer/nav or the cart, or something like that. And the idea is that each parallel route has its own sync/async behavior. I wouldn't create a parallel route for every component on the page. If you are going to do mutations via API route, then RQ or SWR would be fine. If you are going to do them via server action then RQ or SWR would not be necessary and you could use something like `useTransition` to monitor them.
@@jherr i use parallel routes for every independent section on my page with their own error.tsx and loading.tsx files 😭 will keep whatever you've said in mind incase work does decide to move from pages to app great content thanks for the help!
@@MrZiyak99 We are probably talking about the same thing. There is the main content section of the page and then other sections that can be independently rendered/streamed and that's what parallel routes are great for.
That's another option, but in this case that would mean blocking the RSC making the request because it would have to await the request. That would mean that any other components it contained that had additional requests would be blocked on the request.
I found out that server actions are now fully usable in both server and client components and have replaced all of my api routes with those. Integrates amazingly with tanstack query too and its much easier to write them. Is there any downside to this?
I found using server actions for data fetching to have some important limitations. For me the deal breaker was having no built-in way to abort requests, like you would using an AbortController on normal fetch calls. This is a big issue with typeahead server validation or autocomplete requests, where promises may be resolved out of order
I didnt knew this but i faced this performance issue. Thanks Jack for help.
As always ,you are awesome Jack, you keep digging here and there and come out with something incredible like this , and I see the beard coming ,cheers man and tell the wife to let the beard grow
This is the most promising data-fetching and handling video I've seen regarding the new app router! Definitely signing up for Pro NextJS!
jack you absolutely rule! so much of your content helps me at work and quite often; whether its brainstorming, understanding new concepts, or an idea of a new direction to look into. thanks so much and keep it up man!
Thanks! Relatively new React web dev here, and I just wanted to say I am enjoying your lesson
Literally met an issue today that this seems to solve, perfect timing!
Thank you so much. Ive been building all my full stack next apps without using the Api functionality in next. Now I am definitely going to use it.
What an absolute gem! You made it so easy to understand even for a beginner like me!
I'm constantly shocked by how complicated all of this has gotten.
Nice vid! Bonus that I learned about the underscore idea for naming folders... I went back to the docs to read more about how that works.
Is there a particular reason you reached for react-error-boundary instead of the build in error.js file from Nextjs?
Nice work Jack!
Thank you infinitely for the efoort and the knowledge you are spreading with us. May i forward my question or a request let's say... What is the best way to connecr nextjs and a separate backend in term of forming our logic, there are actually ways for example request direct from components or using api routes as a proxy
Nice, this content is so high I'm throwing away my old gummies.
Yeah, don't throw away the new gummies. :)
Thank you so much for explaining this Jack! When passing promises as props, does it mean the 'promise cracking' phrase is happening in React hydration stage? Does it also mean it might affect the CLS if I do not have the right size (dimensions) for a loading component as fallback? Thank you so much again for these awesome video!
`use` is cracking the promise and most likely throwing the promise on render and then React is getting that promise and subscribing to it itself so that when it resolves it will re-render the component. And all that is done on the server side. If you look at the RSC payload you can see a "promise type" marker with the data from the promise, so it's resolved on the server. Then on the client during hydation they use do a Promise.resolve(payload) and pass that in.
@@jherr Hi Jack, Thank you for explaining how the promise works both is RSC and client component! If everything rendered on the server side, would it be the same as SSR in page route and the page load should be fast? I thought I would not even see the loading stage when the html is ready to be served. However when I tried your example with image fetch instead, I would see a loading state before image loaded, rather than seeing the image right away (comparing to page route approach). Does it mean it is slow even when the promise gets resolved on the server?
@@afion113 So if you are going to get the image data on the server, and that image API is slow, then ask yourself, would you rather the customer have an interactive page with a spinner, or a page that is slow to respond? Because the App Router gives you the ability to have a fully interactive page where parts of it stream and become interactive. Where the pages router simply blocks on getServerSideProps which means that the page would simply be slow to repond.
What a great video! So easy to understand and see the power of this pattern. Thanks Jack!
Awesome video. I actually use RTK and RTK query for my projects and hoping to move them into NextJs. Request: Please Can you make a video on using RTK with Next JS . I will be grateful.
Pro tip: when creating files in VSCode you can write the file path. Vs code will automatically create all folders to that file.
Found that feature wery useful when defining routes in app router 🙂
That is an awesome tip! Thanks!
This is mind-blowing! How can you pass a promise over the wire? How is this possible?
Don't you still feel we are introducing many anti patterns for server side components here? 1.Creating a api endpoint for fetch that should be done in the server component not an own api 2.Talking about React Query and such that becomes more obsolete with server side fetching and caching. 3.Using boundary package. The thing for me is that I have not come to face this kind of problem, maybe I will, but still this feels too complex.
Very cool! Great info as always sir!
Would you say that the use hook is production ready? All documentation I could find about it is in the React RFC. 😥
Hey Jack. Huge fan of your stuff. Tried to sign up to the newsletter 3x and I get no response from your ESP. Using fastmail and not in spam. thx
You can send a request directly to team@pronextjs.dev to get registered. The site is still new and there were some issues with the certificates.
Hi Jack! Do you have any references for understanding how client components that receive props from server components are rendered? It’s confusing to me that a client component that receives props from a server component would actually be server-rendered and “blocked” by the fetching in the server component, as you mentioned. What parts of such a client component are actually client-rendered then?
Thanks!
The actual blocking in the "client" component happens on the server side, the rendered component is sent to the client when the server render of the client component is completed. "Client" components are rendered on both the client and the server.
@@jherr In that case, is there a way to render a loading state in place of the client component while the server component is performing the data fetching? Should I use a loading.tsx? Thank you so much!
@@DesolationPhoenix Yeah, if you use the `use` hook then wrap it in a Suspense as shown in the video. If you use the React-Query `useQuery` hook then look at the `isFetching` boolean and render a loading state if it's true (again, as shown in the video.)
@@jherrthank you so much!!!
That question was in my head the whole time while watching the video 😅
Honestly, the way that is handled with rsc is next level. That's so much more convenient.
Btw. are the any good reasons for using react query etc over use + suspense?
Wow...amazing as always.
If you're scaffolding to use app router but grab the football and instead pass the promise to a client component, why not just have the client component fetch with React Query to begin with?
Next Js Guru ❤❤❤ Love from Pakistan ❤❤❤
Hi, Jack. I enjoyed this video a lot! I have one question though. In the documentation of react-error-boundary, the author says it can only be used in a client component. Why does it works fine in a server component in this case?
Server compents can include client components. And client components can include server components and children or rendered props.
Thank you for the nice content. a request, can you please share your environment setup (Terminal with Theme/VSCode theme/fonts)
great video 🙌 I do not understand why we had multiple copy of the data in vdom part 4:47 . what is the cause of this? data is already at page level and in one place. 😕
Anything you pass to a client component as a property is serialized and serialized independently of any other component. That's why the multiple copies. The context is a single copy because we are only sending the prop to the provider client component and then it's sharing it around both on the server and on the client.
thanks for the answer 🙌 I believe some kind of lint rule is needed to avoid this. It is a mistake that a developer can easily make and it can realy hurt the perf.
was it like this before app router?
Interested in the app Router nextjs course. I am just hoping there is purchase power parity, brazillian real is super weak and my Jr salary doesn't go very far
Thank you for these fantastic tips.
had to do a little reading on use() but this is looking really really cool
Hello Jack thank you for your awesome videos. I wanted to ask you a question that I’m struggling for a while. I have two projects one is a nextjs project of a website and the second one is a monorepo project that contains reusable components. These components are published to npmjs and are imported as dependency into the first one. The issue is in the development workflow. I’m trying to link with pnpm link the components packages to ease the workflow and it works but if you have any hook for example useState in any component it will throw an error saying can not read useState of undefined.
Thank you
You probably have competing React versions. So the components are on one version of React and the NextJS server is another. Is this 13? If so you want 18 across the board and probably more specific than that.
FWIW, the best solve here is to bring everything into the monorepo.
@@jherr yes very good point and I checked it all projects are of the same version of react and common dependencies. You can easily test it by recreating two new projects from scratch (we tested it too). One strange thing is that when we where using nextjs 12 this issue was not present after upgrading it to 13 it appeared. I might be wrong but I think it is related to new transpile option in nextjs 13. Before we were using the withTM module.
Oh my god. You just know every aspect of Next.js.
great video! thank you! somehow, after i change to use ReactQuery, the html in the client side component doesn't show up in the html dom. any idea what i might do wrong?
I would be interested to see you make a video exploring Livewire 3. I don't think it gets enough attention from the tech community here on RUclips considering what it's capable of doing.
I do like Livewire, but I'll probably do htmx first because it's hot now (gotta love the YT algorithm) and it has that server-driven mechanic. :)
Which vs code extension are you using in which data is render on vs code itself 6:53 timestamp?It is really cool...
I was thinking the same thing, did you happen to find it?
@@SharunKumar console ninja
What is the name of extension where is counted component renders?
Next js 13 loading hooks very slow when page loaded then its loading hooks and javascript example my sidebar loaded its need hooks to works it take 2s to load hooks when page full loaded my web app look like its lagging
Great vid again jack :)
Always special one for me ❤️
Great video, I am not sure how React query is able to stream HTML for loading indicator first and then foods later without using Suspense. I thought Suspense is the only mechanism to tell React that a certain part of the application is waiting for data.
I need to investigate a little further how RQ is doing this.
I don't think streaming has anything to do with client component.
It's fetching and rendering UI's after reaching the browser!
Does this mean the loading indicator for RQ is replaced with foods by client side bundle. It is not same rendering pattern as React streaming using Suspense ?@@rokonzamann
@@rokonzamann have a look at what’s coming out of the server. It’s holding the connection open then sending more HTML and JS as the streams are resolved. That’s not initiated by the client.
@@jherr Interesting how that might work! Let's wait for your findings.
Will react-query still re-fetch on invalidation in this example? Is it aware of how to make the fetch happen again if it is passed as a prop from server component?
No, it will simply re-request the original promise which will return the original data.
How to get those console looks inline in the ide? 👀
What keyboard you use? sounds nice
whats that terminal u are using to view webpage?
That's quite a bit of extra boilerplate and complexity just to trim the fat from the v-DOM.
Hey love the videos and ive been subbed for a while. Could you please make a video regarding csrf protection in the new app router dir. There seems to be no packages for the new update and there really isn't many videos covering how to create your own either.
Love it, thank you!
What is the "use" hook that you're importing from "react" on 12:33 ? Because i can't find any information about it in React docs. Thanks!
It's in the experimental build of React that the App Router uses.
@@jherr but its not production ready and NextJS don't recommend it in client. What is the alternative ?
insta-subbed to the newsletter lol
Awesome 👍
I'm not sure I understand the benefit of react server components if you're doing promises for props. Like what's even the point then? Seems like you're running in circle by doing this whole shazam, using tanstack query on the frontend would've provided the exact same benefit
A big benefit is that you are making the request off the server. So you get better security and performance. In addition if you need SEO then there is a big benefit to rendering on the server because the HTML is generated on the server and is easier for the bots to handle.
@@jherr I'm talking about this specific use case in the video (promises for props). Performance would be the same since you wait for the promise to finish.
I'm not sure about the security part, what security issues does this prevent that a separate backend wouldn't?
The other flow (with tanstack query for example) would be to fetch from the client from a backend server, then that server can fetch the same way it's being done in the video, only less convenient I guess.
And I might be wrong on this, but server components don't generate HTML on the server (that's being done by renderToString) but instead send the serialized react tree to the client (so not *directly* html)
@@Andreiu2011 So about whether the API is being called from the server or the client. There are several reasons why it's ideal to call from the server. First, NextJS servers are often deployed in the same VPC as the microservices they call, so it's a much faster connection. Second, the microservices don't need to be deployed to the open Internet because they are being called only by the NextJS servers within the VPC. And third, third party APIs often have access keys which shouldn't be sent to the client for security reasons. So making the requests from the server avoids the key leakage. There are more advantages, but those are some of the primary ones.
And "server components don't generate HTML on the server" is pretty easy to test that yourself, just create a NextJS app, start it up and look at the page source in the browser. You will see all the rendered HTML (as well as the VDOM). "View Page Source" shows what comes back from the server, it does not show the current tree. For the current tree you can use the inspector. You can also see the HTML rendered from the server in the Network panel of the inspector as the response to the initial route request. Or you can just curl the server as see what comes back.
Mr Jack set localhost as endpoint, but if we are working with real life project, how do we set the endpoint?
My recommendation is to use middleware to inject an API header key into the request header with the prefix for the API. It might be something like `X-API-Base-URL` or something like that, which you can set however you want in the middleware and then the components pick it up with `headers`.
Super man!
Awesome video. How do you get those long accurate suggestions?
Copy and paste from a previously implemented correct version. I really don't see the need to make you watch me poorly type stuff. :)
@@jherr oh I see. Anyway nice video. I learn a lot of new stuff from you. Thanks man.
Nice, but is there anyway to make RSC to refetch?
try to use router.refresh on the client component or revalidatePath on api route
If we don't include "no-cache" then we wouldn't be "awaiting" for the data in all the components and the components would just reuse the same promise.
And I reckon if we use context for passing the actual data instead of the promise, it should also send only one copy of the data with the vdom
If you a requesting off the client then yeah, they would all pick up the same cache. But that's not going to SSR, so if you want SSR then you have to request the data in an RSC.
Can you please do a video on how to do a PWA using Next JS 13 ( with app router ).
The problem that now error handling is not progressively enhanced. You need JS to handle them
I don't think that's correct. All of the action is happening on the server. So client-side JS or not you would still get the error boundary content (or error.tsx) content coming off the server if there was an error.
@@jherr try to turn off js, you wont get any errors to render. In remix you will. Dan Abramov, explained that there was a missing part for sending errors as an action return. And it’s not implemenred
@@shadowfaxenator You are correct sir. Thanks for the heads up on that one.
I took a break from this channel for a bit, I can't believe you're still talking about NextJS payloads, it's seems like every single video. Using context for promises is a decent pattern but not realistic in the long term. And to make use of Suspense with RQ, it has a flag for that. Just using isFetching by itself is a CSR indicator. And not likely what you want if you want that loading state to float up to a larger component.
What vsc's theme do you use?
Night Wolf [black]
@@jherr Thank you so much!
Thanks
Good content. But it's weird to create context for each entity in my app.
Then have a single context that contains multiple promises.
@@jherr instead of using context, could we use Zustand or Jotai, to achieve the same thing?
@@rubendacostaesilva8442 I wouldn't use Zustand or Jotai in their default "global" mode since globals with App Router are a no-no. Instead I would provide Zustand or Jotai atoms via context so that you are guaranteed that the state managers are per-request. Zustand and Jotai totally support this model, it's just not as super-easy as it usually is. For Zustand for example, you first call a hook that gets the Zustand hook from the context, and then you call the Zustand hook just like before.
@@jherr that's sound kind of "gimmickly", but I'm going to give it a try.
Thanks for the response, and keep up the great work you're doing!
This helped alot thanks
Can we use the error.js and loading.js and not installl additional packages?
I only brought in the external library in the error case for simplicity. An error boundary is a single class component that is ~10 lines of code. But yeah, if you just want a catch-all you can do error.tsx.
What about SEO in this kind of usage? Is it going to be affected? :)
No. Streaming doesn’t effect SEO.
@@jherr thanks :)
I need a robust machine like your
I like you video edit, it's so details. I would love to learn your. Can you please make a course on Udemy?
If we are using Suspense, then I assume even if you pass a promise or await a promise on the server, the user would not notice a difference right ?
It depends on what else you have going on. The await on the server blocks any other components that are also loading.
@@jherr Alright. So essentially you await on the client side using "use" hook instead of the server ! Right ?
@@rajeshdavide That's actually pretty complicated because it's both on the client and the server. "client" components run on BOTH the client and the server. That's number one. So when a "client" component on the server that uses `use` gets a fulfilled promise it renders on the SERVER. The HTML and the data are then both sent to the client where the component instance on the client is hydrated symmetrically and the `use` is run there too.
So if that's the case, can I assume that the fullfilled promise is streamed after the client renders the component ?
Do you have a material where I can read more ?
In my mental model use hook was akin to await, if the client component that uses "use" runs on the server will it not wait until promise is resolved ?
The page source code contains "Foods: Pizza, Burger, Sandwich, Pasta", but not RQ Foods. So no streaming possible with react-query atm
Yeah, I have to take another look at that. There might be a way to get that to work.
Awesome!
thanks very useful 👍
I can't understand why you didn't use loading.tsx and error.tsx to handle the loading and error state instead of using suspense and errorboundary
Loading and error are great to handle the route level errors. Here I'm demonstrating how to manage errors and suspenses at whatever level of granularity you want within the component tree.
Excellent
what theme are you using in vscode ?
Night Wolf [black]
@@jherr thanks 👍
Neat trick but I wonder the benefits, we get no server rendering of data, so doesn't work for no js/crawlers and more complex than an API and use query
What do you mean get no server rendering of data? I showed every time that the data is server rendered. Have a look at the HTML I showed from the page source. That's coming back from the server.
@@jherr I guess not if you disable js, as the promise has the data, and not the html? I guess I can see the value if the API is slow enough you wouldn't want it on initial render maybe
@@griffadev If you look at the output of the server, regardless of whether the client has disabled JavaScript or not, the HTML coming out of the server has all the rendered HTML including the HTML that comes in late off the suspense because the connection is held open until the suspense completes.
@@jherr that makes sense, still getting used to this react sever component world, thanks for the explanation
@@griffadev No problem. The whole client/server isomorphic thing has always been a little complicate when you look into the details. It was simpler with the Pages Router because the flow between getServerSideProps and then rendering, then sending it to the client, and hydrating and running there, blah blah blah, was pretty straightforward. Now, with RSCs and streaming, things are getting more complicated. They are CONSISTENT, which is cool, but complex.
can't you just use the loading and error components in the app router instead?? (error.tsx and loading.tsx in same level as the route.tsx which is currently server side rendering)
This demonstrates using error boundaries and suspenses within the component to all for a finer level of loading and error indication granularity. If you don't need that then feel free to use error and loading.
@@jherr one of the reasons I'm invested in next js is because I don't have to deal with all those states. But I get it 👍
@@josevsebastian2909 you can only use them in pages right , it will wrap up the whole page with the error fallback if something fails , but if u r only using that api response in particular component then I think its best to just wrap that piece of code with error boundary
@@yuvarajyuvi9691 in page router it works like that. Wrapping everything in error boundary and suspense. But one of the main advantages of app router is that, it respects the nested layouts of different routes, only the "page" leaf component is replaced by the boundary, all the "layout" is still rendered. And most often that's the result you want, except when you need granular loading or error handling inside the "page" and even that can be done using parallel routes.
I dont think we need to give underscore for the component name, Nextjs is smart enough to not include it as part of the route page as long it doesnt have page file in it, cmiiw
You don't need to, but this makes it really explicit.
you're just solving the data inside the client component, context, no context, don't matter it's cached.
What's cached again? The only cache that is involved here is the fetch cache which is being turned off in the code.
wooo
console ninja slaps!
👍👍👍👍👍
Love your videos but promises as props just feels wrong.
but if you just await the result and put it into provider you get the exact same result... lol?
promises were irrelevant
I think so
i dont understand why u are using suspense and error boundaries when next has loading.tsx and error.tsx specifically for this. also why use react query here it does not make sense to me. lastly i feel like this is not a common usecase does the next/react team encourage us to do something like this? i feel like situations like this huge payload are fairly uncommon. plz do lemme know cause there is still a lot i need to learn about the app router
error and loading are route level, using suspense gives you the ability to give skeletons/spinners at a component level.
the addition of react-query is the basis of a nice pattern of re-fetch and valuable to folks who already use that library (or SWR) to manage promises. it's just further validation that the promises are indeed promises.
as for common use case, there are lots of use cases. i've personally worked with very large data sets on both client and server side. the nice thing about the App Router is that we are no longer sending everything out of getServerSideProps to the client, now with RSCs some data can remain strictly on the server and we can limit the amount of data going to the client.
@@jherr would parallel routes be a better alternative to the suspense and error boundry situation? also what do you think of the long term use of something like react query and swr with next now pushing to have mutations with fetch? i had never faced this data issue so far (mostly cause we still use pages at work haha) but will keep this in mind!
@@MrZiyak99 parallel routes are for rendering separate sections of the page like the header/footer/nav or the cart, or something like that. And the idea is that each parallel route has its own sync/async behavior. I wouldn't create a parallel route for every component on the page.
If you are going to do mutations via API route, then RQ or SWR would be fine. If you are going to do them via server action then RQ or SWR would not be necessary and you could use something like `useTransition` to monitor them.
@@jherr i use parallel routes for every independent section on my page with their own error.tsx and loading.tsx files 😭
will keep whatever you've said in mind incase work does decide to move from pages to app
great content thanks for the help!
@@MrZiyak99 We are probably talking about the same thing. There is the main content section of the page and then other sections that can be independently rendered/streamed and that's what parallel routes are great for.
Why not just pass the actual data to context and then distribute it this seems just overcomplicaton
That's another option, but in this case that would mean blocking the RSC making the request because it would have to await the request. That would mean that any other components it contained that had additional requests would be blocked on the request.
I found out that server actions are now fully usable in both server and client components and have replaced all of my api routes with those. Integrates amazingly with tanstack query too and its much easier to write them. Is there any downside to this?
I found using server actions for data fetching to have some important limitations.
For me the deal breaker was having no built-in way to abort requests, like you would using an AbortController on normal fetch calls. This is a big issue with typeahead server validation or autocomplete requests, where promises may be resolved out of order