Alaskan donut
Alaskan donut
TtRPC
Created by Alaskan donut on 11/1/2024 in #❓-help
Fetch once and never again?
Hey there 👋, I'm wanting to fetch some data reactionTypes once when my layout <MainLayout /> renders in Nextjs and never again because this data does not change. Currently, I have placed (what I think is) a headless component into my layout that accesses the query client then sets a staleTime: Infinity default on this specific query. Is this a dumb strategy? How might you do this differently?
"use client";

import { trpc } from "@/utils/trpc";
import { useQueryClient } from "@tanstack/react-query";
import { getQueryKey } from "@trpc/react-query";

export function TrpcMainLayoutDefaults() {
const queryClient = useQueryClient();

// Reaction Types
const reactionTypesKey = getQueryKey(trpc.reaction.getTypes);
queryClient.setQueryDefaults(reactionTypesKey, {
staleTime: Infinity,
});
// I had originally prefetched, but it seems this just adds an unneeded request (understandably)
// trpc.useUtils().reaction.getTypes.prefetch()

// Other...

return <></>;
}
"use client";

import { trpc } from "@/utils/trpc";
import { useQueryClient } from "@tanstack/react-query";
import { getQueryKey } from "@trpc/react-query";

export function TrpcMainLayoutDefaults() {
const queryClient = useQueryClient();

// Reaction Types
const reactionTypesKey = getQueryKey(trpc.reaction.getTypes);
queryClient.setQueryDefaults(reactionTypesKey, {
staleTime: Infinity,
});
// I had originally prefetched, but it seems this just adds an unneeded request (understandably)
// trpc.useUtils().reaction.getTypes.prefetch()

// Other...

return <></>;
}
2 replies
TtRPC
Created by Alaskan donut on 10/21/2024 in #❓-help
Opinionated help: Where to place data access functions with respect to tRPC router(s)?
Hey there 👋 I'm currently trying to decide where to place my data access functions with respect to my tRPC routers. Currently, I have them placed at src/data-access/post/mutate-thing.ts, and I am wanting to move them into a folder structure like this: src/server/routers/post/functions/mutate-thing.ts but this feels a bit too nested (maybe not a bad thing) and for someone new to my codebase, this might make it difficult to find these functions. My routers are all obviously defined at src/server/routers, and I import my data access functions directly into each procedure within each router. Should I leave these data functions where they are at?
2 replies
TtRPC
Created by Alaskan donut on 10/14/2024 in #❓-help
Dynamically generate url for httpBatchLink
Hey there 👋 is it possible to generate a url for httpBatchLink instead of hardcoding one? I attempted the below code, but this doesn't work. Understandably, the fallback value is used for url each time the component mounts. I believe that I wouldn't even need a useEffect if I wasn't using Next, as I could directly grab these values from window.location, but since I'm using SSR, this code doesn't make it through the SSR pass.
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import { useEffect, useState } from "react";
import { trpc } from "@/utils/trpc";
import SuperJSON from "superjson";

export function TRPCQueryClientProvider({
children,
}: {
children: React.ReactNode;
}) {
const [url, setUrl] = useState<string | null>(null);

useEffect(() => {
if (typeof window !== "undefined") {
const { hostname, protocol, port } = window.location;
setUrl(`${protocol}//${hostname}:${port}/api/trpc`);
}
}, []);

const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: url ?? "http://localhost:3000/api/trpc", // Fallback in case url is not ready,
// url: "http://192.168.0.16:3000/api/trpc", // For mobile device testing
transformer: SuperJSON,
}),
],
}),
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
);
}
"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import { useEffect, useState } from "react";
import { trpc } from "@/utils/trpc";
import SuperJSON from "superjson";

export function TRPCQueryClientProvider({
children,
}: {
children: React.ReactNode;
}) {
const [url, setUrl] = useState<string | null>(null);

useEffect(() => {
if (typeof window !== "undefined") {
const { hostname, protocol, port } = window.location;
setUrl(`${protocol}//${hostname}:${port}/api/trpc`);
}
}, []);

const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: url ?? "http://localhost:3000/api/trpc", // Fallback in case url is not ready,
// url: "http://192.168.0.16:3000/api/trpc", // For mobile device testing
transformer: SuperJSON,
}),
],
}),
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
);
}
3 replies
TtRPC
Created by Alaskan donut on 9/16/2024 in #❓-help
How to get pageParam from useInfiniteQuery()?
How would I write a tRPC call equivalent to this traditional useInfiniteQuery? My primary concern here is that I need to pass in a cursor to my procedure, and upon each successive query I need to update this cursor for the next call.
const {
data: posts,
isFetching,
error,
hasNextPage,
fetchNextPage,
} = useInfiniteQuery({
queryKey: ["profile-posts", username],
queryFn: ({ pageParam }) =>
kyInstance
.get(
`/api/profiles/${username}/posts`,
pageParam ? { searchParams: { cursor: pageParam } } : {},
)
.json<TProfilePostsPage>(),
initialPageParam: null as string | null,
getNextPageParam: (lastPage) => lastPage.nextCursor,
});
const {
data: posts,
isFetching,
error,
hasNextPage,
fetchNextPage,
} = useInfiniteQuery({
queryKey: ["profile-posts", username],
queryFn: ({ pageParam }) =>
kyInstance
.get(
`/api/profiles/${username}/posts`,
pageParam ? { searchParams: { cursor: pageParam } } : {},
)
.json<TProfilePostsPage>(),
initialPageParam: null as string | null,
getNextPageParam: (lastPage) => lastPage.nextCursor,
});
Maybe it should be something like this?
const [nextCursor, setNextCursor] = useState<string | null>(null)

const {
data: posts,
isFetching,
error,
hasNextPage,
fetchNextPage,
} = trpc.getProfilePosts.useInfiniteQuery({ username, cursor: nextCursor }, {
queryKey: ["profile-posts", username],
initialPageParam: null as string | null,
getNextPageParam: (lastPage) => {
setNextCursor(lastPage.nextCursor)
return lastPage.nextCursor
},
});
const [nextCursor, setNextCursor] = useState<string | null>(null)

const {
data: posts,
isFetching,
error,
hasNextPage,
fetchNextPage,
} = trpc.getProfilePosts.useInfiniteQuery({ username, cursor: nextCursor }, {
queryKey: ["profile-posts", username],
initialPageParam: null as string | null,
getNextPageParam: (lastPage) => {
setNextCursor(lastPage.nextCursor)
return lastPage.nextCursor
},
});
2 replies