Custom Components - Fixing a Form Builder Input Problem
I can see you're working with the older Sanity Studio v2 API using part:@sanity/form-builder. I need to be upfront with you: Studio v2 is no longer supported (support ended December 7, 2023 according to this documentation), and the Parts System has been deprecated in favor of Studio v3's architecture.
The issue you're experiencing is a known limitation with wrapping FormBuilderInput in v2. The focusPath prop is essential for nested editing (like opening array item modals), but it can create infinite render loops when your custom component recursively references itself.
Why this happens:
When you register a custom component for a field type, Sanity uses that component as the inputComponent for that type. When you render <FormBuilderInput> inside your custom component with the same type, it tries to render your custom component again, creating a loop. Omitting focusPath breaks array editing; including it can trigger the loop in certain contexts like field groups.
Potential fix to try:
The key is to remove the inputComponent property from the type definition to break the recursive cycle while keeping focusPath intact:
import React from "react";
import { FormBuilderInput } from "part:@sanity/form-builder";
const WrappedField = React.forwardRef((props, ref) => {
// Remove inputComponent to prevent recursive rendering
const { inputComponent, ...cleanType } = props.type;
const noHeader = cleanType.options?.header === false;
return (
<div className={`tm-object tm-${noHeader ? "without" : "with"}-header`}>
{/* Pass all props INCLUDING focusPath, but with cleaned type */}
<FormBuilderInput {...props} ref={ref} type={cleanType} />
</div>
);
});
export default WrappedField;By stripping inputComponent from the type, you tell FormBuilderInput to use the default renderer instead of your custom one, which should prevent the loop while preserving focusPath for array editing.
The honest recommendation:
Since v2 is no longer supported and I cannot verify v2-specific behavior against current documentation, I'd strongly recommend migrating to Studio v3. The custom input component system in v3 completely avoids these wrapper pattern issues. You define custom components using the components.input property in your schema, and the system handles focus management and nesting automatically without the fragile FormBuilderInput wrapper pattern.
The migration guide provides detailed instructions for transitioning from v2 to v3. If you absolutely cannot migrate right now, try the fix above, but be aware that troubleshooting v2-specific edge cases will only get harder as the platform moves forward.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.