Skip to main content
Version: v7 / v8

Common mistakes

Custom component as closure

Avoid defining custom components for React Query Builder inside the body of another function component. Here's what not to do:

App.jsx
const App = () => {
// Other stuff ...

const CustomValueEditor = props => {
// Custom logic here ...
return <input />;
};

return (
<QueryBuilder
fields={fields}
query={query}
handleOnChange={q => setQuery(q)}
controlElements={{
valueEditor: CustomValueEditor,
}}
/>
);
};

This pattern causes issues like input fields losing focus after each keystroke because CustomValueEditor is recreated on every App render. Instead, declare custom components outside the parent function:

App.jsx
const CustomValueEditor = props => {
// Custom logic here ...
return <input />;
};

const App = () => {
// Other stuff ...

return (
<QueryBuilder
fields={fields}
query={query}
handleOnChange={q => setQuery(q)}
controlElements={{
valueEditor: CustomValueEditor,
}}
/>
);
};

Another common mistake involves creating wrapper arrow functions in JSX. In this example, CustomValueEditor is correctly defined outside App, but assigning an arrow function that renders it (instead of the component itself) creates a new function component on every render:

App.jsx
const CustomValueEditor = props => {
// Custom logic here ...
return <input />;
};

const App = () => {
// Other stuff ...

return (
<QueryBuilder
fields={fields}
query={query}
handleOnChange={q => setQuery(q)}
controlElements={{
// Don't do this:
valueEditor: props => <CustomValueEditor {...props} />,
// Do this instead:
// valueEditor: CustomValueEditor,
}}
/>
);
};