Simple, opinionated data fetching for the Next.js App router. Write all your queries in the same place, and use them across Server and Client Components easily.
Server Actions are great for mutations, and are the de facto way of POSTing data in both Server and Client components. For fetching data, Server Components can just call the query directly - no server action or API route needed. For Client Components though, you have to write route handlers for every single fetch action, and use a third-party client fetching library like React Query. This gets tedious - it would be cool to just be able to call the queries directly like in Server Components!
Troute automatically generates route handlers, and wraps around React Query, allowing you to call those same query functions from Client Components (without having to write all the route handlers.)
queries/user.ts
import db from ...
export const getUser = async ({id}: {id: string}) => {
return await db.findUser(id)
}
Fetching from a Server Component:
import { getUser } from "@/queries/user"
export const User = async () => {
const user = await getUser({id: '123'})
return <div>{user.name}</div>
}
Fetching from a Client Component:
"use client"
import { troute } from '@/troute'
export const User = () => {
const { data: user } = troute.getUser({params: {id: '123'}})
return <div>{user.name}</div>
}
-
Install Troute:
npm install @olifog/troute
-
In your root layout, add a TrouteProvider:
import { TrouteProvider } from '@olifog/troute' // ... export default function App({ Component, pageProps }) { // ... return ( <TrouteProvider> <Component {...pageProps} /> </TrouteProvider> ) }
-
Create an
app/api/troute/route.ts
file:export { GET } from '@/troute'
-
Create a
troute.ts
file in your project root:import { createTroute } from "@olifog/troute"; export const {GET, troute} = createTroute({})
-
Now you can start creating your queries as in the
queries
folder (or whatever other name you want):queries/user.ts
import db from ... export const getUser = async ({id}: {id: string}) => { return await db.findUser(id) }
-
And add any fetch queries you want to call from the client into the createTroute call in
troute.ts
:import { createTroute } from "@olifog/troute"; import { getUser } from "@/queries/user"; export const {GET, troute} = createTroute({ getUser })
An example app using Troute can be found here.