Alaskan donut
Alaskan donut2mo ago

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>
);
}
1 Reply
Alaskan donut
Alaskan donutOP2mo ago
Currently, this seems to work, however if it's likely that the fallback value would ever be used here as opposed to the return of getUrl()
const getUrl = () => {
if (typeof window !== "undefined") {
const { hostname, protocol, port } = window.location;
const url = `${protocol}//${hostname}:${port}/api/trpc`;
return url;
}
return undefined;
};

const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: getUrl() ?? "http://localhost:3000/api/trpc",
// url: "http://192.168.0.16:3000/api/trpc", // For mobile device testing
// You can pass any HTTP headers you wish here
// async headers() {
// return {};
// },
transformer: SuperJSON,
}),
],
}),
);
const getUrl = () => {
if (typeof window !== "undefined") {
const { hostname, protocol, port } = window.location;
const url = `${protocol}//${hostname}:${port}/api/trpc`;
return url;
}
return undefined;
};

const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: getUrl() ?? "http://localhost:3000/api/trpc",
// url: "http://192.168.0.16:3000/api/trpc", // For mobile device testing
// You can pass any HTTP headers you wish here
// async headers() {
// return {};
// },
transformer: SuperJSON,
}),
],
}),
);