Sanity
Get a peek at our latest innovations at Sanity Product Day on Dec 8th →

Custom Components - Fixing a Form Builder Input Problem

5 replies
Last updated: Jul 19, 2022

Hi all, I'm having an issue with a very simple custom component. It's actually just a wrapper around a

FormBuilderInput
to work around the fact that the
object
field in Sanity always displays in an indented manner. This component solves this using some custom CSS.
This works, but the issue is that some fields are not working correctly anymore - an Array of Object items is no longer editable (the edit modal doesn't show). If I add the
focusPath
prop back it does work, but then I run into an infinite loop when used within a field group. Here's the code:
import React from "react";
import { FormBuilderInput } from "part:@sanity/form-builder";

const WrappedField = React.forwardRef((props, ref) => {
  const { inputComponent, ...usableType } = props.type;
  const noHeader = usableType.options?.header === false;
  // omit the focusPath to prevent infinite loop
  const { focusPath, ...properties } = props; 

  return (
    <div className={`tm-object tm-${noHeader ? "without" : "with"}-header`}>
      <FormBuilderInput {...properties} ref={ref} type={usableType} />
    </div>
  );
});

export default WrappedField;

Jul 19, 2022, 2:35 PM

Looks like this is a known issue, and Sanity is aware of this. There's a workaround that pops up in several repos on GH, most managed by Sanity staff: https://github.com/nrkno/nrkno-sanity-libs/blob/8723908ddba1628f3aa3954fb264a44dc0[…]ges/sanity-plugin-nrkno-odd-utils/src/lib/NestedFormBuilder.tsx -

user T
I saw you used this elsewhere too.
This solves my issue:


import React from "react";
import { NestedFormBuilder } from "./NestedFormBuilder";

const WrappedField = React.forwardRef((props, ref) => {
  const { inputComponent, ...usableType } = props.type;
  const noHeader = usableType.options?.header === false;

  return (
    <div className={`tm-object tm-${noHeader ? "without" : "with"}-header`}>
      <NestedFormBuilder {...props} ref={ref} type={usableType} />
    </div>
  );
});

export default WrappedField;

Jul 19, 2022, 2:49 PM

Correct. You can get an infinite loading loop when trying to decorate a built-in field. That’s what this hook does .

Jul 19, 2022, 3:32 PM

Thanks for confirming this! However, doesn't

const { inputComponent, ...usableType } = props.type;
take care of this already? I'm omitting
inputComponent
, but perhaps I'm misunderstanding the hook?

Jul 19, 2022, 3:37 PM

(To be clear I didn’t write this hook, another of our developers did, I just know it solved my issue 🙂 )

Jul 19, 2022, 3:39 PM

I see ... the main problems I faced were focus/interaction related, the infinite loop you mentioned did not occur - it was only when I passed on

focusPath
that things were recursing indefinitely.

Jul 19, 2022, 3:40 PM

Sanity.io: Get the most out of your content

Sanity.io is a platform to build websites and applications. It comes with great APIs that let you treat content like data. Free to get started, and pay-as-you-go on all plans. Find out more.