Confusion with server component fetching and suspense in a generic way
Answered
American Wirehair posted this in #help-forum
American WirehairOP
I'm confused as how to best approach this. Ideally we'd like a generic component which fetches data and passes it to children, and my current approach for this is to call a function. However, with this, my loading spinner is never showing.
Is there a better way to achieve what I want that'll actually work?
I saw previous discussion about
(Note: ArrangementPie is a client component)
On my page:
Fetcher (use server at top of file):
Is there a better way to achieve what I want that'll actually work?
I saw previous discussion about
use()
but I can't wrap my head around it for my use case.(Note: ArrangementPie is a client component)
On my page:
<Suspense fallback={<CenteredLoadingSpinner />}>
<Fetcher fetch_fn={fetch_arrangement_data} children_fn={data => (
<ArrangementPie data={data}/>
)} />
</Suspense>
Fetcher (use server at top of file):
export async function Fetcher <T>({
children_fn,
fetch_fn,
error = null,
}: FetcherProps<T>) {
try {
const data = await fetch_fn();
return children_fn(data);
} catch (e) {
console.error("Error fetching data:", e);
return error;
}
}
Answered by American Wirehair
"use server";
interface FetcherProps<T> {
children: (data: T) => React.ReactNode;
fetch_fn: () => Promise<T>;
error?: React.ReactNode;
}
export async function Fetcher <T>({
children,
fetch_fn,
error = null,
}: FetcherProps<T>) {
try {
const data = await fetch_fn();
return children(data);
} catch (e) {
console.error("Error fetching data:", e);
return error;
}
}
11 Replies
American WirehairOP
something like this works but isnt ideal/flexible and doesnt seem right
export async function Fetcher <T>({
ChildComponent,
fetch_fn,
error = null,
}: FetcherProps<T>) {
try {
const data = await fetch_fn();
return <ChildComponent data={data} />;
} catch (e) {
console.error("Error fetching data:", e);
return error;
}
}
doesn’t even work half the time
there 100% is a better way that i dont know
American WirehairOP
alternatives i guess could also be some query library hook or using a route handler, but this data we’d prefer to not need to manage an api route for
American WirehairOP
im also open to just inlining the call to the function in the page and passing that to the chart as shown [here](https://nextjs.org/docs/app/getting-started/fetching-data#with-an-orm-or-database), but its unclear whether this blocks the whole page rendering until a result or not
and in general this doc just confused me more than it helped
American WirehairOP
i really dont want to have to colocate it the standard way, i have 16 different charts to wrap and would just create insane boilerplate
American WirehairOP
bump
American WirehairOP
ok, i didnt realise you could just set children type as a function rather than need a new param, it seems to work now without freaking out about what functions are on the client and server
still no idea if its the right way to do it but it works
American WirehairOP
"use server";
interface FetcherProps<T> {
children: (data: T) => React.ReactNode;
fetch_fn: () => Promise<T>;
error?: React.ReactNode;
}
export async function Fetcher <T>({
children,
fetch_fn,
error = null,
}: FetcherProps<T>) {
try {
const data = await fetch_fn();
return children(data);
} catch (e) {
console.error("Error fetching data:", e);
return error;
}
}
Answer