#TanStack Start + Query + db access example
1 messages · Page 1 of 1 (latest)
I can't share the repository I'm working on but are you more interested in the architecture or the setup (e.g. how things are wired up)?
I'm trying to get things cleanly organised to avoid any accidental direct calling of server code from client code (mostly due to copying across NextJS server actions into the app). What I've come up with for now is -
// /routes/contacts.tsx
export const Route = createFileRoute('/contacts')({
component: ContactsPage,
loader: ({ context }) => {
context.queryClient.prefetchQuery(contactsQueryOptions())
},
ssr: false,
})
function ContactsPage() {
const contacts = useContacts()
return ( ... )
}
// /components/contacts/useContacts.tsx
export const contactsQueryOptions = () =>
queryOptions({
queryKey: ['contacts'],
queryFn: async () => await getContactsSF(),
})
export default function useContacts() {
const { data: contact } = useQuery(contactsQueryOptions())
return contact
}
// /lib/server/contactsServer.ts
export const getContactSF = createServerFn({ method: 'GET' })
.validator((data: number) => data)
.handler(async (ctx) => getContact(ctx.data))
export const getContactSF = createServerFn({ method: 'GET' })
.validator((data: number) => data)
.handler(async (ctx) => getContact(ctx.data))
export const addContactSF = createServerFn({ method: 'POST' })
.validator((data: NewContact) => data)
.handler(async ({ data }) => await addContact(data))
// /lib/db/contacts.ts
export async function getContact(contactId: number) {
const result = await db.query.contacts.findFirst({
where: (contacts, { eq }) => eq(contacts.id, contactId),
})
return result
}
export async function addContact(contact: NewContact) {
const result = await db.insert(contacts).values([contact])
return result.changes
}