
react-query-builder
βVisual query builder component for React β zero dependenciesβ
A headless React component library for building visual query interfaces. Drop it into any React app to let users construct complex filter queries with AND/OR groups, field pickers, and operator selectors. Works with any data source.
Installation
Requirements
React 18 or newer
Optional but strongly recommended
npm install
Install from npm
npm install react-query-builderQuick Start
Add a query builder to your React app in 2 steps
Install the package
Install from npm
npm install react-query-builder
# or
yarn add react-query-builderπ‘ Tips
- β’Requires React 18+
- β’TypeScript is supported out of the box
Render the QueryBuilder
Pass your fields config and listen for onChange
import { QueryBuilder } from 'react-query-builder';
const fields = [
{ name: 'name', label: 'Name', type: 'text' },
{ name: 'age', label: 'Age', type: 'number' },
{ name: 'status', label: 'Status', type: 'select',
options: ['active', 'inactive', 'pending'] },
];
export function FilterPanel() {
const [query, setQuery] = useState({ combinator: 'and', rules: [] });
return (
<QueryBuilder
fields={fields}
query={query}
onQueryChange={setQuery}
/>
);
}You're all set! Check out the detailed usage guide below for more advanced features.
Usage Guide
Basic filter query
Build a simple filter with AND/OR combinators
const [query, setQuery] = useState({
combinator: 'and',
rules: [
{ field: 'status', operator: 'equals', value: 'active' },
],
});
<QueryBuilder fields={fields} query={query} onQueryChange={setQuery} />Output
Renders a visual query builder with a single rule rowExport to SQL WHERE clause
Convert the query object to a SQL WHERE expression
import { formatQuery } from 'react-query-builder';
const sql = formatQuery(query, 'sql');
// "status = 'active' AND age > 18"
const json = formatQuery(query, 'json');API Reference
QueryBuilder
The main React component. Renders an interactive visual query builder.
Signature
QueryBuilder(props: QueryBuilderProps): JSX.ElementParameters
fieldsFieldConfig[]RequiredArray of field definitions (name, label, type, options)
queryRuleGroupRequiredControlled query state object
onQueryChange(query: RuleGroup) => voidRequiredCalled whenever the query changes
fieldEditorComponentsRecord<string, React.ComponentType>Custom renderer components keyed by field type
Returns
JSX.ElementExamples
<QueryBuilder fields={fields} query={query} onQueryChange={setQuery} />formatQuery
Converts a RuleGroup to a string representation (SQL, JSON, or MongoDB)
Signature
formatQuery(query: RuleGroup, format: 'sql' | 'json' | 'mongodb'): stringParameters
queryRuleGroupRequiredThe query object from QueryBuilder state
format'sql' | 'json' | 'mongodb'RequiredOutput format
Returns
stringExamples
formatQuery(query, 'sql') // "name = 'Alice' AND age > 18"validateQuery
Validates a query for completeness β returns errors for empty rules or invalid operators.
Signature
validateQuery(query: RuleGroup, fields: FieldConfig[]): ValidationResultParameters
queryRuleGroupRequiredThe query to validate
fieldsFieldConfig[]RequiredField definitions used to validate field names and types
Returns
ValidationResult β { valid: boolean; errors: string[] }Examples
const { valid, errors } = validateQuery(query, fields);Examples
Real-world code examples and use cases
User filter with export to SQL
beginnerBuild and export a user filter query
function UserFilter({ onFilter }) {
const [query, setQuery] = useState({ combinator: 'and', rules: [] });
const fields = [
{ name: 'email', label: 'Email', type: 'text' },
{ name: 'role', label: 'Role', type: 'select', options: ['admin', 'editor', 'viewer'] },
];
return (
<>
<QueryBuilder fields={fields} query={query} onQueryChange={setQuery} />
<button onClick={() => onFilter(formatQuery(query, 'sql'))}>Apply Filter</button>
</>
);
}Nested AND/OR groups
intermediateExample of complex nested query structure
const complexQuery = {
combinator: 'or',
rules: [
{
combinator: 'and',
rules: [
{ field: 'role', operator: 'equals', value: 'admin' },
{ field: 'status', operator: 'equals', value: 'active' },
],
},
{ field: 'email', operator: 'endsWith', value: '@company.com' },
],
};Server-side validation with Zod
intermediateValidate the formatted query on the API route
import { z } from 'zod';
const AllowedFields = z.enum(['email', 'role', 'status']);
const AllowedOperators = z.enum(['equals', 'contains', 'startsWith']);
const RuleSchema = z.object({
field: AllowedFields,
operator: AllowedOperators,
value: z.string().max(200),
});
const result = RuleSchema.safeParse(incomingRule);Related Content
Explore related articles, projects, and tools.