Fetching Data in Layout
Answered
Spectacled bear posted this in #help-forum
Spectacled bearOP
I want to fetch data in the layout but also adding a loding screen. how can I acheive this? like in the file convention section it says that the suspense component is a child of the layout so it will not be rendered at all unless the data is fetched which not enables me to add loading screen. another solution is to handle the loading screen without the loading.tsx component as we do in normal react but it won't be accepted since I will need to use states and that is not accepted in the server components (which the layout.tsx is considered one) so how can I do it?
51 Replies
you shouldn't fetch data inside a layout. A layout is for "layout-ing" stuff. Not for fetching stuff. Create a layout, if you want to layout stuff. If you want a layout or not, you still want to fetch data somewhere: fetch data inside your server components. So create a page.js for your route, fetch your stuff and you are ready to go. @Spectacled bear
Spectacled bearOP
And what If there is a component that is common between all my pages but I need data from my database to render it??? I don't think your description of a layout is very accurate because every UI (even if it's layout) could depends on some data coming from an API
I don't see solution other than repeating fetching the data in each page which is very bad DX
@Spectacled bear And what If there is a component that is common between all my pages but I need data from my database to render it??? I don't think your description of a layout is very accurate because every UI (even if it's layout) could depends on some data coming from an API
the layout itself should never depend on any data. The components that will be layouted, they have data.
Just to get that right that's a layout: https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/s_A8CA686DA97A9B54A10BB8506B0F905A3FEF553C480B7AEBFFA08B417AE4ABF7_1642170540124_Untitled.png?resize=2048%2C1200&ssl=1
And you see: no data. Just layouting
Just to get that right that's a layout: https://i0.wp.com/css-tricks.com/wp-content/uploads/2022/05/s_A8CA686DA97A9B54A10BB8506B0F905A3FEF553C480B7AEBFFA08B417AE4ABF7_1642170540124_Untitled.png?resize=2048%2C1200&ssl=1
And you see: no data. Just layouting
@Spectacled bear I don't see solution other than repeating fetching the data in each page which is very bad DX
what about a file that contains your querys?
Spectacled bearOP
I got you but still whatever you call the component that is common between all my pages (assuming it's not layout based on your defenetion), what should I do if I don't want to repeat typing it inside every page?
actually my layout is very similar to the picture you sent
but I have the user data to render in the header
how can I fetch them???
of course with keeping it on the server for SEO
you would create for each container (like sidebar, header, ..) a component. These components will be layouted inside your layout (so that they are on the right position). The components, for example the header, will then fetch it's data inside the header server component. You can do this by using:
If you also need the data inside your sidebar, you can think of rewrite the code also inside your sidebar or if you don't want all this, then you can render only your page (without layout) and layout the stuff inside your page.js. You can also fetch the data inside the page.js. Then you can pass them as props down the tree.
I recommend you my first version, because you have more control over components, layouts, pages. You also don't need to worry about "to many requests" to the backend, because they will be cached by vercel. So everything is fine with both solutions
By the way: please don't just close this thread. I just found it, because I am interested to help you, like you see on this message.
export default ... {
const fetchedUserData = getCurrentUser();
return ... render your data ...
}If you also need the data inside your sidebar, you can think of rewrite the code also inside your sidebar or if you don't want all this, then you can render only your page (without layout) and layout the stuff inside your page.js. You can also fetch the data inside the page.js. Then you can pass them as props down the tree.
I recommend you my first version, because you have more control over components, layouts, pages. You also don't need to worry about "to many requests" to the backend, because they will be cached by vercel. So everything is fine with both solutions
By the way: please don't just close this thread. I just found it, because I am interested to help you, like you see on this message.
@Spectacled bear of course with keeping it on the server for SEO
does it work for you?
Spectacled bearOP
Actually after deep thoughts I figured out that if there is a content that is important for SEO it would not be related to a layout as you said and it should be fetched inside a page which solves my problem. And if there is a data that is needed to render the layout it should be dynamic data (like user info) which is not used at all in the SEO so there would be no problem in fetching it on the client and that's why ai felt this question is wrong so I closed it.
Thank you so much you brought this to my mind
Thank you so much you brought this to my mind
@Spectacled bear Actually after deep thoughts I figured out that if there is a content that is important for SEO it would not be related to a layout as you said and it should be fetched inside a page which solves my problem. And if there is a data that is needed to render the layout it should be dynamic data (like user info) which is not used at all in the SEO so there would be no problem in fetching it on the client and that's why ai felt this question is wrong so I closed it.
Thank you so much you brought this to my mind
wait wait wait, you fetch the data now on the clientside??? Because it's not relevant for seo???
Spectacled bearOP
No the layout still server component but inside the layout there is a small component that is marked with "use client" which I fetch the user info inside it using useSWR and handle loading skeleton there but the layout at general and the page still server side and still fetching the main content on the server
Actually my English can be a little bit bad but I solved the problem without sacrificing anything
well, that's not how to solve problems... but if you want to live with that like that, then you do what you do 🙂
Spectacled bearOP
What fo you mean and where is the issue with my solution???
I mean, that data fetching should in nearly every case on the serverside. And you now just created a clientcomponent and fetch it clientside...
Spectacled bearOP
Will I don't think that is right like every fetch should be on the server
@Spectacled bear Like the solution you provided still don't handle the loading state for better UX
I thought you know, that when you fetch stuff in a page component, that you then add a loading.js file, to apply loading states.... 🤔
Spectacled bearOP
Especially for a very dynamic data like the user info
@Spectacled bear Will I don't think that is right like every fetch should be on the server
why do you think that it's not right to fetch everything serverside?
@B33fb0n3 I thought you know, that when you fetch stuff in a page component, that you then add a loading.js file, to apply loading states.... 🤔
Spectacled bearOP
Well no you said that I should create a header and sidebar components inside my layout
That's where you can't handle loading state
if I just going to add them to may page instead of the layout then I will need to repeat them in every page
@B33fb0n3 why do you think that it's not right to fetch everything serverside?
Spectacled bearOP
Because it's a better user experience. Like instead of showing a whole loading screen you only show him the parts loading as skeleton and the parts that is static will still there rendered
yea, that's what I am talking about... let me show it to you... (give me a second)
Spectacled bearOP
Ok please
The layout I described you:
This is your layout: It's rendered for every page inside your route group.
Inside your page.js you load and display your data like it told you:
And YES you DON'T need to add your Header and Footer and Sidebar and whatever to your page. It's inside the layout. And the layout surround every page.
The loading can also be added to your routes
const Layout = ({ children }) => {
return (
<div>
<YourHeaderComp />
<YourSidebarComp />
<div className="mainContent">{children}</div>
<YourFooterComp/>
</div>
);
};This is your layout: It's rendered for every page inside your route group.
Inside your page.js you load and display your data like it told you:
export default ... {
const fetchedPageData = getPageData();
return ... render your data ...
}And YES you DON'T need to add your Header and Footer and Sidebar and whatever to your page. It's inside the layout. And the layout surround every page.
The loading can also be added to your routes
Spectacled bearOP
Well where is the data fetching part inside the header and sidebar??? 😅😅😅
I want from you to fetch data inside the header and add loading state handling on the seever
Because I see that's impossible to do it on the server
@Spectacled bear Well where is the data fetching part inside the header and sidebar??? 😅😅😅
the Header is also a server component. You can use the same fetching method like you done in the page:
export default YourHeaderComp ... {
const fetchedUserData = getUserData();
return ... render your data ...
}Spectacled bearOP
Adding loading.js will only work for the page
Not for the layout comps
oh, yeah... 🤔
Spectacled bearOP
So I can't add loading.js for the header right??????
let me check that... maybe there is something wrong in my brain...
Spectacled bearOP
No actually I feel bad that I didn't explain very well
Use a
Suspense if you want to add a loading component for individual componentsSpectacled bearOP
Can you show me an example I feel that's what we were looking for
And I really appreciate the time @B33fb0n3
Answer
Here u go
Spectacled bearOP
Yup that's what I was looking for
thanks to both of you @Clown @B33fb0n3
Also read React's docs for how this changes the loading sequence and stuff and in general how suspense works:
https://react.dev/reference/react/Suspense#revealing-nested-content-as-it-loads
https://react.dev/reference/react/Suspense#revealing-nested-content-as-it-loads