Implementing wsLink causes issues on React

I get an error within the console stating
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'onError')
at Object.onError (createHooksInternal-f1d4019d.mjs:454:41)
at Object.error (index.mjs:80:17)
at Object.error (index.mjs:20:25)
at Object.error (observable-ade1bad8.mjs:55:21)
at Object.error (observable-ade1bad8.mjs:55:21)
at httpBatchLink-cee1f56c.mjs:200:34
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'onError')
at Object.onError (createHooksInternal-f1d4019d.mjs:454:41)
at Object.error (index.mjs:80:17)
at Object.error (index.mjs:20:25)
at Object.error (observable-ade1bad8.mjs:55:21)
at Object.error (observable-ade1bad8.mjs:55:21)
at httpBatchLink-cee1f56c.mjs:200:34
Solution:
Found my issue! The solution it to change App.tsx ```tsx import routes from "./pages/_routes"; import { RouterProvider } from "react-router-dom"...
A
AlwayzPatrick195d ago
App.tsx
import routes from "./pages/_routes";
import { RouterProvider } from "react-router-dom"

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createWSClient, httpBatchLink, wsLink } from '@trpc/client';
import { useState } from 'react';
import { trpc } from '@/util/_trpc';
import Cookies from "js-cookie";

function App() {
const headers: any = {};
if (Cookies.get("token")) {
headers["authorization"] = `Bearer ${Cookies.get("token")}`;
}

const ws = createWSClient({
url: import.meta.env.VITE_WS_TRPC ?? "",
})
const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: import.meta.env.VITE_API_TRPC ?? "",
// You can pass any HTTP headers you wish here
async headers() {
return {
...headers
};
},
}),
wsLink({
client: ws
})
],
}),
);

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={routes} fallbackElement={<h1>Loading...</h1>} />
</QueryClientProvider>
</trpc.Provider>
);
}

export default App;
import routes from "./pages/_routes";
import { RouterProvider } from "react-router-dom"

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createWSClient, httpBatchLink, wsLink } from '@trpc/client';
import { useState } from 'react';
import { trpc } from '@/util/_trpc';
import Cookies from "js-cookie";

function App() {
const headers: any = {};
if (Cookies.get("token")) {
headers["authorization"] = `Bearer ${Cookies.get("token")}`;
}

const ws = createWSClient({
url: import.meta.env.VITE_WS_TRPC ?? "",
})
const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: import.meta.env.VITE_API_TRPC ?? "",
// You can pass any HTTP headers you wish here
async headers() {
return {
...headers
};
},
}),
wsLink({
client: ws
})
],
}),
);

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={routes} fallbackElement={<h1>Loading...</h1>} />
</QueryClientProvider>
</trpc.Provider>
);
}

export default App;
Home.tsx
import { trpc } from "@/util/_trpc";

export default function Home() {
const healthyQuery = trpc.healthy.useQuery();
const onPermission = trpc.users.user.permissions.onGive.useSubscription();

return (
<div>
<h1>Home</h1>
<p>Server is {healthyQuery.data === "OK" ? "Healthy" : "Dead"}</p>
<p>This is the home page.</p>
</div>
);
}
import { trpc } from "@/util/_trpc";

export default function Home() {
const healthyQuery = trpc.healthy.useQuery();
const onPermission = trpc.users.user.permissions.onGive.useSubscription();

return (
<div>
<h1>Home</h1>
<p>Server is {healthyQuery.data === "OK" ? "Healthy" : "Dead"}</p>
<p>This is the home page.</p>
</div>
);
}
Changing the link to a split link and checking on the operation "subscription" causes the error
uncaught TypeError: Cannot read properties of undefined (reading 'onStarted')
at Object.onStarted (createHooksInternal-f1d4019d.mjs:443:41)
at Object.next (index.mjs:72:21)
at Object.next (index.mjs:15:25)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (wsLink.mjs:259:34)
at handleIncomingResponse (wsLink.mjs:119:13)
at WebSocket.<anonymous> (wsLink.mjs:135:17)
uncaught TypeError: Cannot read properties of undefined (reading 'onStarted')
at Object.onStarted (createHooksInternal-f1d4019d.mjs:443:41)
at Object.next (index.mjs:72:21)
at Object.next (index.mjs:15:25)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (observable-ade1bad8.mjs:48:21)
at Object.next (wsLink.mjs:259:34)
at handleIncomingResponse (wsLink.mjs:119:13)
at WebSocket.<anonymous> (wsLink.mjs:135:17)
Solution
A
AlwayzPatrick195d ago
Found my issue! The solution it to change App.tsx
import routes from "./pages/_routes";
import { RouterProvider } from "react-router-dom"

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createWSClient, httpBatchLink, wsLink, splitLink } from '@trpc/client';
import { useState } from 'react';
import { trpc } from '@/util/_trpc';
import Cookies from "js-cookie";

function App() {
const headers: any = {};
if (Cookies.get("token")) {
headers["authorization"] = `Bearer ${Cookies.get("token")}`;
}

const ws = createWSClient({
url: import.meta.env.VITE_WS_TRPC ?? "",
})
const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
splitLink({
condition(op) {
return op.type === "subscription";
},
true: wsLink({
client: ws
}),
false: httpBatchLink({
url: import.meta.env.VITE_API_TRPC ?? "",
// You can pass any HTTP headers you wish here
async headers() {
return {
...headers
};
},
}),
}),
],
}),
);

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={routes} fallbackElement={<h1>Loading...</h1>} />
</QueryClientProvider>
</trpc.Provider>
);
}

export default App;
import routes from "./pages/_routes";
import { RouterProvider } from "react-router-dom"

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createWSClient, httpBatchLink, wsLink, splitLink } from '@trpc/client';
import { useState } from 'react';
import { trpc } from '@/util/_trpc';
import Cookies from "js-cookie";

function App() {
const headers: any = {};
if (Cookies.get("token")) {
headers["authorization"] = `Bearer ${Cookies.get("token")}`;
}

const ws = createWSClient({
url: import.meta.env.VITE_WS_TRPC ?? "",
})
const [queryClient] = useState(() => new QueryClient());
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
splitLink({
condition(op) {
return op.type === "subscription";
},
true: wsLink({
client: ws
}),
false: httpBatchLink({
url: import.meta.env.VITE_API_TRPC ?? "",
// You can pass any HTTP headers you wish here
async headers() {
return {
...headers
};
},
}),
}),
],
}),
);

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={routes} fallbackElement={<h1>Loading...</h1>} />
</QueryClientProvider>
</trpc.Provider>
);
}

export default App;
So it has a split link and only split when the operation is a subscription.
A
AlwayzPatrick195d ago
In the actual file you need to change the code to access the observer.
import { trpc } from "@/util/_trpc";

export default function Home() {
const healthyQuery = trpc.healthy.useQuery();
trpc.users.user.permissions.onGive.useSubscription(undefined, {
onStarted() {
console.log("Started");
},
onData(data) {
console.log(data);
}
});

return (
<div>
<h1>Home</h1>
<p>Server is {healthyQuery.data === "OK" ? "Healthy" : "Dead"}</p>
<p>This is the home page.</p>
</div>
);
}
import { trpc } from "@/util/_trpc";

export default function Home() {
const healthyQuery = trpc.healthy.useQuery();
trpc.users.user.permissions.onGive.useSubscription(undefined, {
onStarted() {
console.log("Started");
},
onData(data) {
console.log(data);
}
});

return (
<div>
<h1>Home</h1>
<p>Server is {healthyQuery.data === "OK" ? "Healthy" : "Dead"}</p>
<p>This is the home page.</p>
</div>
);
}
I could've known this since its the same syntax for a normal client which I did implement but I guess I just was tired :)
A
AlwayzPatrick195d ago
Possibly adding some examples on how to use wsLink in React for the docs would be handy :)
K
kamama191d ago
here is a problem, if the user haven't signin. The websocket connection is created using the cookie without session token. Once you signed in, the websocket connection is still without session token, we have to recreate the connect . only two way to solve the issue, 1: wslink expose reconnect method, 2: create the client in React component
A
AlwayzPatrick191d ago
Yep hence I use the React component trpc.Provider It should reload the connection each time on mount
More Posts
Understanding how too reuse TRPC with React Server ComponentsHopefully I am understanding this correctly, but I have created a `experimental_createTRPCNextAppDirWhat would be considered best practice for getting data and invalidating queries?I have a really simple task management app (doing it to learn stuff). Tasks are grouped in projects Calls to specific table not working in production, fine locallyI am having a strange issue since yesterday. I am using nextjs TRPC and Prisma to connect to a planeanyone else getting a failed to fetch in latest next versionsnot sure if this is happening to more people, I tried literally everything, changing to 127.0.01, upMissing keys in TRPCError when returning as JSONHey all! I am returning a TRPCError from a custom TRPC server but only the code and name keys seems How to close a Standalone adapter server?I want to run some integration tests with Vitest and for some reason I don't want to use the `createtRPC Client within Next.js but with external standalone server?Hi, I have an old Next.js project that used tRPC and we're currently in the process of separating oReview of inner and outer context with expressHello, I didn't find any example that uses inner (for testing) and outer context with express. ThatShould i use lint rule explicit-function-return-type when use trpc?I got warning for this lint https://typescript-eslint.io/rules/explicit-function-return-type/ When how to delete next-auth modules from trpc stacjas the title saysWrapper Component: Unable to retrieve application context.Hello tRPC-Community, I have ran into a funny "issue" while gaining my first experiences with tRPC. handling errors server sideHow do you guys handle server side errors 500 request on productionit sound like handle upload/download file need build new http server or endpoint?I have scan all posts i can about solution for handle upload/download file with trpc.So there is no tRPC queries running on the serverEnvironment: - bun 1.0.2 - next 13.4.16 - trpc 10.37.1 I am creating an app with `next-intl` and `nName recommendations for my api endpoints that use swagger, trpc-panel, trpc-playground.What name do you recommend for each one, in addition to the rest api and the trpc api endpoints. LiIn the context should I put all my dependencies for my endpoint handlers?For example I have the end point 'getStuff` In this endpoint the handler call 3 party apis and map Basic Inference not WorkingI have been struggling to get basic type inferencing to work with trpc, react, and Drizzle ORM. ThitRPC Websockets with a standalone Bun Server?Hey folks! Experiementing with setting up a standalone tRPC Server using Bun. The HTTP part is greaInfinite session query when tab is in backgroundSo, when I am in development mode, doing some changes in my code and my application's tab is not in How to return a stream? like open ai apiI want that my api can have stream responses like open ai https://github.com/openai/openai-node#stre