tRPC and REST

We're considering building tRPC Nextjs base systems which pull data from Strapi via REST calls. So, instead of using getServerSideProps, I am thinking we will would create a router and define procedures which each make appropriate REST calls to Strapi. Is this the right approach? Your comments and thoughts would be appreciated. Thanks!
10 Replies
cje
cje2y ago
yes, using tRPC as a "backend-for-frontend" makes sense bonus points if you validate the response from strapi with zod before sending it back to the client
benten
benten2y ago
Do you want to do SSR/prerendering or is fetching client-side enough? Are you going to be typing your responses from Strapi?
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
cje
cje2y ago
getServerSideProps also runs on the server
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
benten
benten2y ago
The only benefit of doing it without SSR is that you get strong types - but if the data coming from Strapi isn't typed, then it's pointless
ibamsey
ibamsey2y ago
Thanks for the responses. SSR is would be nice as would strong types. I've got this largely working, however, has anyone a good example of REST gets from a tRPC router with typing/response validation?
rocawear
rocawear2y ago
So if I want my site have good SEO I should use ssr: true? Didn't understand the strong types part, I did some testing and would this be good and strongly typed endpoint for client to consume? I am trying to understand would it be good to use trpc on project where I need to get data from headless cms / external api for example and hide my api key. If I need good SEO I should use ssr with trpc?
import { z } from "zod";
import axios from "axios"
import { router, publicProcedure } from "../trpc";

export const ProductsResponse = z.array(
z.object({
id: z.number(),
title: z.string(),
price: z.number(),
description: z.string(),
category: z.string(),
image: z.string(),
rating: z.object({
rate: z.number(),
count: z.number(),
}),
})
);

export type TProductsResponse = z.infer<typeof ProductsResponse>;

export const productsRouter = router({
all: publicProcedure.output(ProductsResponse).query(async () => {
const { data } = await axios.get("https://fakestoreapi.com/products");
const products = ProductsResponse.parse(data);
return products;
}),
});
import { z } from "zod";
import axios from "axios"
import { router, publicProcedure } from "../trpc";

export const ProductsResponse = z.array(
z.object({
id: z.number(),
title: z.string(),
price: z.number(),
description: z.string(),
category: z.string(),
image: z.string(),
rating: z.object({
rate: z.number(),
count: z.number(),
}),
})
);

export type TProductsResponse = z.infer<typeof ProductsResponse>;

export const productsRouter = router({
all: publicProcedure.output(ProductsResponse).query(async () => {
const { data } = await axios.get("https://fakestoreapi.com/products");
const products = ProductsResponse.parse(data);
return products;
}),
});
And would this be basically the same with only using react query? So if I just need couple of endpoints to hide my api key is it worth to use trpc for it instead of creating couple normal api endpoints and parsing data there also?
const {
data,
isLoading,
isError,
} = useQuery({
queryKey: ["products"],
queryFn: async () => {
const { data } = await axios.get(`https://localhost:3000/api/products`);
return ProductsResponse.parse(data);
},
});
const {
data,
isLoading,
isError,
} = useQuery({
queryKey: ["products"],
queryFn: async () => {
const { data } = await axios.get(`https://localhost:3000/api/products`);
return ProductsResponse.parse(data);
},
});
My api endpoint that I could consume using react query like above:
import type { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";

import { ProductsResponse, type TProductsResponse } from "@schemas/products";

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<TProductsResponse>
) {
const { data } = await axios.get("https://fakestoreapi.com/products");
const products = ProductsResponse.parse(data);
res.status(200).json(products);
}
import type { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";

import { ProductsResponse, type TProductsResponse } from "@schemas/products";

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<TProductsResponse>
) {
const { data } = await axios.get("https://fakestoreapi.com/products");
const products = ProductsResponse.parse(data);
res.status(200).json(products);
}
ibamsey
ibamsey2y ago
@rocawear thanks for this, much appreciated and really helpful. I've been working with plain old fetch(). Your code uses axios. I'm just wondering (noob!) what's the primary reason you have used axios over plain fetch ?
rocawear
rocawear2y ago
habbit, its does not matter what you use. I think axios throws error but fetch does not i think axios is more mature for production because it has more features
Want results from more Discord servers?
Add your server