Build a Prisma Filter UI with React Query Builder
Build a product filter and preview the Prisma where object before validating it on your server.
What this recipe builds
- A product filter with list, number, and yes/no fields.
- Filter rules that users can review before sending them.
- A clear separation between browser filter state and server-side Prisma execution.
Loading the interactive recipe demo...
Install and imports
Install / imports
npm install @vojtechportes/react-query-builder
Fields and initial query
Typed field configuration
import type {DenormalizedQuery,IBuilderFieldProps,} from '@vojtechportes/react-query-builder';export const fields: IBuilderFieldProps[] = [{field: 'category',label: 'Category',type: 'LIST',value: [{ label: 'Books', value: 'BOOKS' },{ label: 'Games', value: 'GAMES' },],},{ field: 'price', label: 'Price', type: 'NUMBER' },{ field: 'inStock', label: 'In stock', type: 'BOOLEAN' },];export const initialQuery: DenormalizedQuery = [{type: 'GROUP',value: 'AND',isNegated: false,children: [{ field: 'inStock', operator: 'EQUAL', value: true }],},];
Builder implementation
React implementation
import '@vojtechportes/react-query-builder/styles.css';import React from 'react';import {Builder,type DenormalizedQuery,type IBuilderFieldProps,} from '@vojtechportes/react-query-builder';import { formatQuery } from '@vojtechportes/react-query-builder/formatQuery';const fields: IBuilderFieldProps[] = [{field: 'category',label: 'Category',type: 'LIST',value: [{ label: 'Books', value: 'BOOKS' },{ label: 'Games', value: 'GAMES' },],},{field: 'price',label: 'Price',type: 'NUMBER',operators: ['EQUAL', 'LARGER_EQUAL', 'SMALLER_EQUAL'],},{ field: 'inStock', label: 'In stock', type: 'BOOLEAN' },];const initialQuery: DenormalizedQuery = [{type: 'GROUP',value: 'AND',isNegated: false,children: [{ field: 'inStock', operator: 'EQUAL', value: true }],},];export const PrismaFilter = () => {const [query, setQuery] = React.useState(initialQuery);const submit = async () => {const formatted = formatQuery(query, 'Prisma', {fields,wrapWhereClause: true,});const { where } = JSON.parse(formatted) as { where: unknown };await fetch('/api/products/search', {method: 'POST',headers: { 'content-type': 'application/json' },body: JSON.stringify({ where }),});};return (<><Builder fields={fields} data={query} onChange={setQuery} /><button onClick={submit}>Search products</button></>);};
Export the Prisma where input
Export the Prisma where input
const where = formatQuery(query, 'Prisma', {fields,wrapWhereClause: true,});
Expected output
{ "where": { "AND": [{ "inStock": { "equals": true } }] } }
Validation and safety
- Treat the browser-produced object as untrusted input.
- On the server, accept only supported fields and operators, then validate value types and query depth.
- On the server, add filters that restrict records to the current user or organization.
Production notes
- Wait briefly after the user stops editing before updating expensive previews, and require a Submit action for expensive searches.
- Keep Prisma Client and database credentials on the server.
Related guides
Frequently asked questions
Where should the Prisma query run?
On the server. Send the Builder data to your API, check it there, and then create and run the Prisma query.
Can users change a required filter, such as their organization ID?
You can lock the rule in the UI, but the server must add or verify required filters because browser data can be changed.