Using TRPC in Astro and its (React) islands
I started using TRPC in some Next.js projects at work, and really liked the end-to-end type safety this gives you as a developer when working with APIs. So I decided to also implement TRPC on my own website, which is using Astro. There’s a few steps that need to be taken to start using TRPC in Astro.
Installing the required packages
Setting up the TRPC context
Because I want to check the currently logged in user when a TRPC route is called, I add the getUser()
call from @astro-auth
. By adding this to the context, I can use the user later on in my middleware (see below).
Setting up the TRPC server
I created a separate procedure adminProcedure
, on which I applied the middleware. This will make sure that any route on this procedure can only be called if there is a logged in user.
After creating the procedures, I declare the different routes. Check the deleteCommentForBlog
route which is the route behind the adminProcedure
.
Setting up the API Route in Astro
I’ll be using the fetch adapter to handle the requests from the client side to the TRPC router.
This is possible because Astro uses the built-in Web Platform APIs Response
& Request
.
We link the router and the context, and we’re ready to set up the TRPC client.
Setting up the TRPC client
Because I want to use TRPC both in client side scripts on Astro pages, as well as on islands. My islands are created using React, to I’ll set up the TRPC React client too.
Using the TRPC client in .astro files
I’ll be using the Astro TRPC client to communicate from my <script>
tag on the client to the TRPC routes.
Because I’m using the TRPC client, I get autocompletion on the code, and I know exactly what is expected as input for the route and what will be returned!
Using the TRPC client in React islands
I decided to work with @tanstack/react-query
to facilitate easier fetching/mutating in my React code.
Because of this, I needed to instantiate the TRPC client and a QueryClient
for react-query
.
This I did in a wrapper component, which wraps the actual component which will be doing the calls to the TRPC routes.
The actual component ended up looking like this:
So fetching all comments is as easy as adding const upToDateCommentQuery = trpcReact.getAllComments.useQuery()
.
Deleting a comment is done by adding const { mutate: deleteComment } = trpcReact.deleteCommentForBlog.useMutation
and then in my <button>
’s click handler calling deleteComment({ id: comment.id });
.
Hope this was helpful! Code can be found on my GitHub.