In a classic App to read from the database, you need some code to run on a server layer somewhere and share the data via REST with your client code. Blitz makes this process a lot easier using queries.
Blitz queries are plain, asynchronous JavaScript functions that always run on the server. Instead of calling an endpoint Blitz will allow you to import that code directly into your front end code so you don't need to build an API and do data fetching from the frontend. At build time, Blitz automatically inserts an API call that runs the server code on the server. Essentially, Blitz abstracts your API into a compile step.
Queries must be inside queries folder
Example:
app/queries/getPost.ts
app/posts/queries/getPost
app/admin/posts/queries/getPost
To read from the database you can use the db
package e.g db.{modelName}.findOne
.
To a single post, your query should look like this
import { NotFoundError } from "blitz"
import db, { FindOnePostArgs } from "db"
type GetPostInput = {
where: FindOnePostArgs["where"]
}
export default async function getPost({ where }: GetPostInput) {
const post = await db.post.findOne({ where })
if (!post) throw NotFoundError
return post
}
Another cool thing with Blitz is that React Concurrent Mode is enabled by default. So the <Suspense>
component is used for loading states and <ErrorBoundary> is used to display errors. If you need, you can read the React Concurrent Mode Docs.
In order to use a query on your React component, you need to wrap them in <Suspense>
.
Example:
import { useParams, useQuery } from "blitz"
import getPost from "../../posts/queries/getPost"
import { Suspense } from "react"
const Post = () => {
const params = useParams()
const [post] = useQuery(getPost, { where: { slug: params.slug as string } })
return (
<div>
<h1>Post: {post.title}</h1>
</div>
)
}
const PostPage = () => {
return (
<Suspense fallback={<span>Loading...</span>}>
<Post />
</Suspense>
)
}
export default PostPage