#How to properly handle data fetching when multiple components share data.

19 messages · Page 1 of 1 (latest)

gleaming citrus
#

I am working on a basic website currently and having a bit of a blocker when it comes to data fetching.

In my root layout, I have a Header and Footer component. In my CMS I have a "Settings" global.

Both the Header and the Footer need data from Settings to render. Initially, before I had the Footer, I just did my data fetching for settings inside the Header component.

Now I need both components to access the data I am not sure what to do. I could do the data fetching in the layout file and pass it as props but I have read that I shouldn't be doing this?

I could also do the data fetching for each component individually but this seems redundant and not the right way to go about it.

Any insight would be useful, thank you!

dry jayBOT
dense ravine
#

My usual approach would be to create a reusable function (something like fetchSettings) and reuse that across both the header and footer.

gleaming citrus
#

I was more worried about doubling up on my data fetching

#

feels like I should fetch it once and then use it in each component

dense ravine
#

For that I usually wrap the function in react cache(). That ensures it only runs once per request / render cycle.

This means you can add it pretty much wherever you want and you won’t get redundant api requests.

trim anvil
#

👍 @dense ravine

use unstable_cache https://nextjs.org/docs/app/api-reference/functions/unstable_cache

To get globals create a function like the following and use it like

const footerData: Footer = await getCachedGlobal('footer', 1)()

import type { Config } from 'src/payload-types'

import configPromise from '@payload-config'
import { getPayload } from 'payload'
import { unstable_cache } from 'next/cache'

type Global = keyof Config['globals']

async function getGlobal(slug: Global, depth = 0) {
  const payload = await getPayload({ config: configPromise })

  const global = await payload.findGlobal({
    slug,
    depth,
  })

  return global
}

/**
 * Returns a unstable_cache function mapped with the cache tag for the slug
 */
export const getCachedGlobal = (slug: Global, depth = 0) =>
  unstable_cache(async () => getGlobal(slug, depth), [slug], {
    tags: [`global_${slug}`],
  })

API Reference for the unstable_cache function.

compact badger
#

Why is it not recommended to fetch data in the layout? It seems like that is the whole point of a serverside component

dense ravine
trim anvil
compact badger
trim anvil
#

you are the one who wrote:

Why is it not recommended to fetch data in the layout? It seems like that is the whole point of a serverside component
What did you want to contribute?

compact badger
#

I was genuinely asking a question. OP mentioned data fetching in the layout is not recommended

#

Probably a moot question, since there is no other way to dynamically build a header/footer

trim anvil
#

... data fetching in the layout is not recommended
Probably a moot question, since there is no other way to dynamically build a header/footer
You have no clue, right?

compact badger
#

Do you have something productive to add?

trim anvil
dense ravine
#

Hi @trim anvil, as @compact badger mentioned, he was just asking a question.

Please be kind, thank you.