How to access a D1 binding from a next.js tsx file (NOT .ts)?
In my next on pages app, I got a db call working on a .ts file but I'm wondering how I access that data within a tsx page? I've read all the documentation but I don't see any next.js examples of calling data within a .tsx server component, only from a .ts file (which I can't import bc of this error in the screenshot).
Open to any suggestions :PES_CryHug:
17 Replies
I believe the issue here is that "use client" directive - you cannot call your D1 directly from a client component
Try using a server action for that
@thipperz if I get rid of that directive though, I can't use
useEffect
and I'm not sure how i'd get that db call to be made on page load. Maybe there's another way to achieve that that I'm not aware ofYup you should not remove "use client". Instead, create a server action that calls the database and forwards the results to your client component.
A "server action" is an async function that is exported from a file that begins with the "use server" directive.
For example in app/actions/index.ts:
Then you can import this new function and use it from your client components. Notice how server actions act like a bridge between client components and parts of your app that cannot be imported from them (usually because of a "server-only" clause, that is useful to avoid leaking sensitive data to the client
Ahh ok I'm gonna try this, thanks
Let me know if it works for you
I think I'm close...
./actions.ts
./page.tsx
gives me:
The data that you return from a server action must be serializable - what are u returning from your GET function?
Lol great question. I've been trying to console.log it to see haha
I got this from the docs at
https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/#access-bindings-in-the-application
and also referenced the next.js db example call in this:
https://blog.cloudflare.com/blazing-fast-development-with-full-stack-frameworks-and-cloudflare
I never tried importing the GET method of a route handler before lol
I mean I have no idea if that code should work, but if it should, you could try awaiting the json method to finish before returning the response
await Response.json(data.results)
If this does not work, you could try moving that DB call to a .ts file and returning the results directly instead of having them being encapsulated by a Response
For example if you move it to a lib/db/index.ts
file:
Then you would import this into your server action and finally import that action in your client componentoh let's go
axing the Response wrapper object in the return from the db call .ts file gave me some progress
man why on earth would that work
json is serializable right... that was the return object type. Weird.
hmm did you try adding the "await" I said? Like
await Response.json(data.results)
because I believe Promises are not serializableOk so I did a return await on the db call:
and on the actions.ts
and then the .tsx file:
oh im an idiot. Had to take it out of the
setData
function. doh
@thipperz thanks so much man, you were a huge help. Really appreciate it
you're a life saver lol
:peepoHappyhug:You're welcome!
I also learned a few things from your case lol
But I'm actually a bit confused about this:
Because I believe route handlers (any route.ts file) must return either a Response or a NextResponse object (?)
I did get an error on returning a non-Response object from the db call at one point, but that setup above works for me so… idk lol
If there is a better way to do this, I can’t find one anywhere online. In the docs or otherwise
Which is weird considering how basic this is for making any kind of app
I’m boutta hit the hay for tonight but I’ll show my configs tomorrow morning in here and hopefully that will help
To start off, you'll need to set your env variables in your
wrangler.toml
file (as per the docs https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/#use-bindings-in-your-nextjs-application)
Then if you're using .ts you generate the types using
npm run build-cf-types
(found that on https://blog.cloudflare.com/blazing-fast-development-with-full-stack-frameworks-and-cloudflare)
Create your route:
(taken from https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/#access-bindings-in-the-application)
Then to avoid conflicts with mixing client/server component imports, create a getter file.
After @thipperz helped me with this I remember reading something on about this pattern on either stackoverflow or the next.js docs but don't remember the link. Oh well.
Then FINALLY to be able to use the data inside your actual .tsx file with html markup:
The process of getting the data into your .tsx file was pretty poorly documented on the Cloudflare docs, but it could be assumed knowledge, and I'm pretty new to react and next.js so...
@GM note that my instructions are for accessing data from a Cloudflare D1 instance, if you're using an external DB from somewhere else then this prob won't help you too muchThis is a good guide on server actions btw:
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
Data Fetching: Server Actions and Mutations | Next.js
Learn how to handle form submissions and data mutations with Next.js.