Best practice for global data access across many pages

I have a use case where I need to be able to display a shared set of data across many pages, regardless of if the user is authenticated or not.

To give examples of use cases:

  • Team name
  • Brand Styles
  • Team logo

This information is stored in the Team model in Prisma, and can be fetched via a unique ID I have access to on the front-end.

This information is needed in common components such as the site Header (Navigation), but also need to be able to show a 404 if that ID does not exist.

Some options I see:

Use the Header as a cell. This requires extra graphql call and data fetching. So you see “Loading…” in a navigation item. Which is quite odd.
Updated tried this out: on a fast connection, this is not noticeable. But open up dev tools and switch to “Fast 3G”. The flashes of “Loading” in both the header and container is very noticeable and quite jarring to the user I imagine.

Move the Header out of the layout, and inside the pages, and add the graphql query to existing calls. This causes the whole page to go blank or show “Loading…”

1 - your cell Loading state can render anything … it does not have to render the phrase Loading. It can render a placeholder or skeleton or spinner or temporary image — or nothing at all.

2 - I’d look into Apollo caching so that the cell doesn’t have to make a query if it already had that consistent header or other branded team data.

Yes, since posting, I have used the following

export const beforeQuery = (props) => {
  return { variables: props, fetchPolicy: 'cache-first' }

That does help to prevent the extra query fetch each time.

Yes, I am aware I can customize that. It’s hard to explain. but in a UI, especially something as critical as navigation, it looks terrible and out of place to have a loading skeleton, or spinner etc. I will try some other solutions.

Another problem I’ve run into is that when I know the object does not exist, I should prevent any of the other cells from rendering. So it looks like I need to call the query in other cells too. As I have not found a way to share that data, fetched from the Header cell.

So as the most basic example, if the object does not exist, I could render a different type of header, and then for the container below it, that renders the page, I need to show a message the Team does not exist.

I had the same issue in another project, and the best solution I could come up with was using cookies. The first time is still slow, but after that it’s fast.

For “No Team” issue, instead of customizing the render of each part, have you thought about create a “Team Does Not Exist” page (with any header you want), and redirect the client to that page?

1 Like

ran into a similar situation; am torn between implementing my own custom hook / context / provider & using cells with aggressive caching

I think we’ll start with the latter + prop drilling, and if it feels like it’s starting to get out of hand will switch to the former. There’s a bug right now with cells receiving children, but once that’s fixed I could see wrapping components in a cell to provide hook-like functionality (using the cache as the provider)

re: seeing a loading state in the nav, if it’s just a skeleton where the logo / name ultimately appear I’m not sure that’s so weird. Definitely seen that pattern elsewhere, anyway

1 Like