Next.js Discord

Discord Forum

best way to pass props to deeply nested serverside component?

Answered
Peterbald posted this in #help-forum
Open in Discord
PeterbaldOP
so I am fetching some data in layout.tsx and there's a route component deeply nested below that I need the data in. Is there a "hack" to pass the prop? (e.g. setting a property on the request object, or in a header)
Answered by riský
however if you just need to store data you can be funny and: https://github.com/manvalls/server-only-context/blob/main/src/index.ts
View full answer

50 Replies

PeterbaldOP
I figured i can just do this:
const serverState = new Map();

export function setServerState(key: string, value: Object) {
    serverState.set(key, value);
}

export function getServerState(key: string) {
    return serverState.get(key);
}

export function deleteServerState(key: string) {
    serverState.delete(key);
}

seems a bit hacky tho, maybe theres a better way...
you should make a "helper" utils file and use react cache to retur the data you wat in both places and then you call it in them and only one db request will occure
but your solution kinda does same thing
Wouldnt this be a candiate for a provider context??
"serverside component"
pass it into the provider from the server component?
we dont need to use client things if all on server
Ohhh sorry
I see.
I misread it as deeply nested client component in a server component 😄
@riský *but your solution kinda does same thing*
PeterbaldOP
ok so apparently my solution stops working when fast refreshed (? not sure why)
does react cache solve this problem? I'm going to try it
Tonkinese
Yes try the react cache approach. But remember that the value can’t be accessed in a client component
PeterbaldOP
yes it has secrets in it... i would hope it cannot be accessed in client
Tonkinese
It can’t so you are safe there.
PeterbaldOP
import { User } from "@/types";
import { cache } from "react";

interface State {
    key2: number; // for testing
    user: User;
}

type Keys = keyof State;

const state = new Map<Keys, State[Keys]>();
const serverState = cache(() => state);

export function setServerState<K extends Keys>(key: K, value: State[K]) {
    const cacheInstance = serverState();
    console.log("setting", key, value);
    cacheInstance.set(key, value);
}

export function getServerState<K extends Keys>(key: K): State[K] | undefined {
    console.log("getting", key, serverState());
    const cacheInstance = serverState();
    return cacheInstance.get(key) as State[K] | undefined;
}

export function deleteServerState<K extends Keys>(key: K) {
    const cacheInstance = serverState();
    cacheInstance.delete(key);
}

this gives the same behaviour as before
i haven't really found anny examples of using React.cache
so im not sure if this is right
im using it as if it's useMemo without dependencies
the problem:
- when I fast refresh the deeply nested child server component, the Map becomes empty (?)
note that setServerState is called in a layout.tsx
PeterbaldOP
ok i think it's actually not possible to fix this issue with fast refresh
use it like this (ofc the "good way")
@riský use it like this (ofc the "good way")
PeterbaldOP
fast refresh still makes it undefined for some reason? anyways here's what I tried:
// state.ts
const serverState = new Map<Keys, State[Keys]>();
export const cachedState = cache(() => serverState);

// nested page.tsx
export default function Page() {
  const state = cachedState();
  const data = state.get("data");
  console.log("server state", data);
  return /* ... */;
}

// layout.tsx
export default function Layout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
  const state = cachedState();
  state.set("user", sessionUser.user);
  return /* ... */;
}


it works initially, but if I edit the nested page.tsx file and trigger a fast refresh, the state becomes undefined again...
im suspecting it has something to do with how I import state.ts and the serverState is defined
that isnt what i meant, just put your fetching alg or smth inside
i think this might work
however if you just need to store data you can be funny and: https://github.com/manvalls/server-only-context/blob/main/src/index.ts
Answer
tysm bro
i love this solution
np i rememberd it was using cache but looked through my huge history to find :)))
PeterbaldOP
can i ask why next.js doesn't have this
natively
like
no one likes prop drilling
me not know
but this is kinda hacky but funny
@riský but this is kinda hacky but funny
PeterbaldOP
is there any downsides?
usually hacky solutoins are
"not best practices"
ok i dont know the legitimacy
but what type of data do you want to share
and why cant you do it in the properly designed cache (ie fetch and do things there to get deduped)
PeterbaldOP
a lot of user data, and it's also streamed
but this solutions feels right
Note: when navigating on the client side the layout is not re-rendered, so you need to set the context both in the page and in the layout.
this is good to know tho