Guidelines on encoding query parameters for a tRPC query with the fetch function

As stated in the tRPCs official documentation, the query parameters must adhere to this specific format:

myQuery?input=${encodeURIComponent(JSON.stringify(input))}

Here is an example of a procedure:

  hello: publicProcedure
    .input(z.object({ text: z.string() }))
    .output(z.object({ greeting: z.string() }))
    .query(({ input }) => {
      return {
        greeting: `Hello ${input.text}`,
      };
    }),

An attempt to manually create a URL results in an error:

const data = {text: "my message"}
const res = await fetch('http://localhost:3000/api/trpc/example.hello?batch=1&input='+encodeURIComponent(JSON.stringify(data)), { method: 'GET' });
const body = await res.json();
console.log(body);

The error suggests that there might be an issue with the encoding of the query parameters. Any insights on what could be going wrong here? Interestingly, it works using the client:

const test = api.example.hello.useQuery({ text: "my message" });

{
    "error": {
        "json": {
            "message": "[\n  {\n    \"code\": \"invalid_type\",\n    \"expected\": \"object\",\n    \"received\": \"undefined\",\n    \"path\": [],\n    \"message\": \"Required\"\n  }\n]",
            "code": -32600,
            "data": {
                "code": "BAD_REQUEST",
                "httpStatus": 400,
                "stack": "...TRPCError and more details..."
                "path": "example.hello"
            }
        }
    }
}

I examined the query sent by the client (

const test = api.example.hello.useQuery({ text: "my message" });
) through my browser, which resulted in success.

http://localhost:3000/api/trpc/example.hello?batch=1&input=%7B%220%22%3A%7B%22json%22%3A%7B%22text%22%3A%22my%20message%22%7D%7D%7D

If I decode the input query parameter, I get

{"0":{"json":{"text":"my message"}}}

Even when I structure my data object in the same manner and encode it accordingly, the query still fails:

const data = {"0":{"json":{"text":"my message"}}}
const res = await fetch('http://localhost:3000/api/trpc/example.hello?batch=1&input='+encodeURIComponent(JSON.stringify(data)), { method: 'GET' });
const body = await res.json();
console.log(body);

The presence of the 0 seems to be necessary due to batching being enabled. However, the inclusion of the json field seems peculiar.

{"0":{"json":{"text":"my message"}}}

Any thoughts on why my constructed fetch request is failing? What would be the correct format for encoding or structuring the object?

Answer №1

It's important to note that the specific structure required for your request will vary depending on how tRPC is configured in your setup, including your links and transformer settings. Without seeing the contents of data for each request, it's difficult to determine if your request is structured correctly.

With that in mind, let's approach this from a more generalized perspective.

The presence of the json key in your requests likely stems from using superjson as your transformer, which is common in many tRPC templates like Create T3 App or example projects on tRPC's GitHub. Superjson simplifies sending complex data types, such as Dates, that can be challenging with standard JSON.

Regarding the batch functionality, your understanding is correct. However, you have the flexibility to adjust this behavior based on the ending link. If batching isn't desired, using httpLink instead of httpBatchLink is an option (though batch linking is generally recommended).

Here are some sample requests, presented in a readable format without URI encoding:

Using superjson with httpBatchLink:

http://localhost:3000/api/trpc/example.hello?batch=1&input={"0":{"json":{"text":"from tRPC"}}}

Using superjson with httpLink:

http://localhost:3000/api/trpc/example.hello?input={"json":{"text":"from tRPC"}}

Without superjson using httpBatchLink:

http://localhost:3000/api/trpc/example.hello?batch=1&input={"0":{"text":"from tRPC"}}

Without superjson using httpLink:

http://localhost:3000/api/trpc/example.hello?input={"text":"from tRPC"}

If you prefer a more traditional REST-style communication with your tRPC API, consider exploring trpc-openapi.

Answer №2

Remember to include the transformer as superjson when setting up your tRPC client with superjson.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What steps should I take to resolve the eslint issue indicating that a TypeScript props interface is not being utilized, even though it is being used?

One of my components utilizes AvatarProps for its props: Below is the interface declaration for AvatarProps: export interface AvatarProps { userName: string; userLastName: string; userImg?: string; onPress?: Function; backgroundColorAvatar?: str ...

Converting Angular 5 select option values to strings is a must

I have set up a basic select connected to a variable like this: <select id="client" name="client" [(ngModel)]="order.clientId"> <option *ngFor="let client of clients" [value]="client.id"> {{ client.name }} </option> </ ...

"The application is experiencing issues due to a malfunctioning JWT secret in NextAuth

[I am currently using Next.js (11.1.2) in combination with NextAuth (4.0.0-beta.7) to authenticate into a Strapi API, utilizing only the Credentials provider (JWT).] The entire authentication flow is "working" with this [...nextauth].js: import NextAuth f ...

Why do Material UI components fail to render in jsdom while using Jest?

During my UI testing using Jest/React Testing Library, I encountered a peculiar issue. In one of my components, the return statement is structured as follows: const sidebarContentUp = ( <Drawer anchor="left" onClose={onMobileC ...

Error: The TypeScript aliases defined in tsconfig.json cannot be located

Having trouble finding the user-defined paths in tsconfig.json – TypeScript keeps throwing errors... Tried resetting the entire project, using default ts configs, double-checked all settings, and made sure everything was up-to-date. But still no luck. H ...

Having trouble with uploading images on Amazon S3 and sharing them on Facebook? Learn how to set the correct meta tag "og:image" in Next

As I work on coding to enable sharing my website page on Facebook, I have utilized meta tags for open graphs. Previously, the images were stored on the server and linked in the meta tag like this: <meta key="og:image" property="og:image" content ...

Guide to iterating through an Observable<Object[]> to generate an array of objects

Google Firestore collection named users is structured as follows : { "contactNumber":"0123456789", "email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="88e2e7e0e6ece7edc8efe5e9e1e4a6ebe ...

Encountering the error message "TypeError: Cannot access property 'Token' of undefined" while compiling fm.liveswitch

The fm.liveswitch JavaScript Software Development Kit (SDK) is designed for use with both clients and your own backend "app server". It functions smoothly in the frontend thanks to webpack and babel. However, the same import statement: import liveswitch fr ...

What is the process for listening to custom events in Angular 4 components that have been loaded using routing?

In the app.component.html file <li routerLinkActive="active current"> <a [routerLink]="['/stats']"> Cluster stats </a> </li> When we route to the DisplayAllStatsComponent, how can we ...

What is the best way to display an image along with a description using Firebase and next.js?

I am currently utilizing Firebase 9 and Next.js 13 to develop a CRUD application. I am facing an issue where the images associated with a post are not correctly linked to the post ID. Furthermore, I need guidance on how to display these images in other com ...

The error message states that the property 'registerUser' is not found on the class 'UserController'

In the controller file, I exported two functions (registerUser and loginUser) as default. No errors were thrown at that stage, but when attempting to access the routes, an error occurred stating - Property 'registerUser' does not exist on type &a ...

Error encountered in NextJS SSR: Axios Z_BUFFER_ERROR

The problem at hand I encountered an issue with my NextJS app that pre-fetches data from an API for SSR. While the client-side operation is running smoothly, I am facing difficulties on the server side (specifically Vercel) where this error message keeps ...

An error occurred when attempting to use the getDoc() function from Firebase within Next.js: TypeError - reading 'map' on properties of undefined

Hello everyone at StackOverflow, I ran into a problem while attempting to use .map() on a getDoc() constant in my Next.js application. The error message I'm getting is: "TypeError: Cannot read properties of undefined (reading 'map')". As a n ...

Guide to configuring a function to display the maximum value on a boxplot in Highcharts

I'm currently using Angular in combination with the highcharts boxplot API. While I am aware that I can manually set the max value of the y-axis in the chart configuration, such as: max: 100, tickInterval: 10. There's now a need for me to dynami ...

Oops! The basePath must always begin with a forward slash "/", but it looks like it starts with a period "." instead. This error was encountered

I am encountering an issue while trying to include '.' in my baseurl. The error message indicates: Error: Specified basePath has to start with a /, found "." const nextConfig = { basePath: '.', reactStrictMode: true, ...

Encountering repetitive pageview events in GA4 while using NextJS

Currently, I am in the process of migrating a NextJS application to GA4. Initially, when the page loads, events are being sent as expected. However, when navigating to subsequent pages by clicking a link generated by Next's Link component, pageview e ...

Utilizing form data binding with multiple instances of forms in React

Parent Component Within my parent component, named Users, there is a snippet of code that includes the functions for adding and updating users: addUser(index, user) { var users = this.state.users var existingUser = users[index] if (existingUse ...

Trouble encountered with uploading files using Multer

I am facing an issue with uploading images on a website that is built using React. The problem seems to be related to the backend Node.js code. Code: const multer = require("multer"); // Check if the directory exists, if not, create it const di ...

Modifying the values of various data types within a function

Is there a more refined approach to enhancing updateWidget() in order to address the warning in the else scenario? type Widget = { name: string; quantity: number; properties: Record<string,any> } const widget: Widget = { name: " ...

Tips for integrating Bootstrap 4.5 variables into NextJS seamlessly

I have a new concept in mind - integrating Bootstrap 4.5 into NextJS and customizing variables as demonstrated here: The structure of my files is within the pages folder: _app.js import '../styles/main.scss' function MyApp({ Component, pageProp ...