Blitz queries and mutations are plain, asynchronous Javascript functions that always run on the server.
We automatically alias the root of your project, so import db from 'db'
is importing <project_root>/db/index.ts
Example Query:
Copy
import db , { FindOneProductArgs } from "db" ;
export default async function getProduct ( args : FindOneProductArgs ) {
const product = await db . product . findOne ( args ) ;
return product ;
}
Example Mutation:
Copy
import db , { ProductCreateArgs } from "db" ;
export default async function createProduct ( args : ProductCreateArgs ) {
const product = await db . product . create ( args ) ;
return product ;
}
# Using Queries# Queries In a React ComponentBlitz provides a useQuery
hook, which is built on react-query
. The first argument is a query function. The second argument is the input to the query function. The third argument is any valid react-query configuration item.
At build time, the direct function import is swapped out for a function that executes a network call to run the query serverside.
React Concurrent Mode is enabled by default for Blitz apps. 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 .
Copy import { Suspense } from "react" ;
import { useRouter , useQuery } from "blitz" ;
import getProduct from "/app/products/queries/getProduct" ;
import ErrorBoundary from "app/components/ErrorBoundary" ;
function Product ( ) {
const router = useRouter ( ) ;
const id = parseInt ( router . query . id as string ) ;
const [ product ] = useQuery ( getProduct , { where : { id : props . query . id } } ) ;
return < div > { product . name } </ div > ;
}
export default function ( ) {
return (
< div >
< ErrorBoundary
fallback = { error => < div > Error : { JSON . stringify ( error ) } </ div > }
>
< Suspense fallback = { < div > Loading ... </ div > } >
< Product />
</ Suspense >
</ ErrorBoundary >
</ div >
) ;
}
# Queries On the ServerIn getStaticProps
, a query function can be called directly without useQuery
Copy import getProduct from "/app/products/queries/getProduct" ;
export const getStaticProps = async context => {
const product = await getProduct ( { where : { id : context . params ? . id } } ) ;
return { props : { product } } ;
} ;
export default function ( { product } ) {
return < div > { product . name } </ div > ;
}
In getServerSideProps
, pass a query function to ssrQuery
which will ensure appropriate middleware is run before/after your query function.
Copy import { ssrQuery } from 'blitz'
import getProduct from '/app/products/queries/getProduct'
export const getServerSideProps = async ( { params , req , res } ) => {
const product = await ssrQuery ( getProduct , { where : { id : params . id } } , { req , res } ) )
return { props : { product } }
}
export default function ( { product } ) {
return < div > { product . name } </ div >
}
For more details, read the comprehensive Query & Mutation Usage Issue
# Using MutationsMutations are called directly, like a regular asynchronous function.
At build time, the direct function import is swapped out for a function that executes a network call to run the mutation server-side.
Copy import { useQuery } from 'blitz'
import getProduct from '/app/products/queries/getProduct'
import updateProduct from '/app/products/mutations/updateProduct'
import { Formik } from 'formik' ;
function ( props ) {
const [ product ] = useQuery ( getProduct , { where : { id : props . id } } )
return (
< Formik
initialValues = { product }
onSubmit = { async values => {
try {
const product = await updateProduct ( values )
} catch ( error ) {
alert ( 'Error saving product' )
}
} } >
{ }
</ Formik >
)
}
For more details, read the comprehensive Query & Mutation Usage Issue