Common mistakes
Custom component as closure
When defining custom components for React Query Builder, do not define them within the body of another function component like this:
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 will almost certainly lead to undesirable behavior such as the value editor losing focus after each keystroke. This happens because the CustomValueEditor
component is being redefined each time the App
component renders. To fix the problem, move the custom component declaration outside of the other function component (it can still be in the same file, just not within the function body):
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,
}}
/>
);
};
A similar mistake that leads to the same problems is declaring arrow functions that render components inside the JSX syntax. In the code below, CustomValueEditor
is correctly defined outside the body of App
, but an arrow function that renders CustomValueEditor
is assigned to valueEditor
instead of the CustomValueEditor
component itself. This causes a new function component to be created on every render.
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,
}}
/>
);
};