I’m trying to insert an item into an array in a custom input component but nothing happens.

5 replies
Last updated: Oct 6, 2020
Can anyone help me here? I’m trying to insert an item into an array in a custom input component but nothing happens. I’m importing PatchEvent like this,
import PatchEvent from 'part:@sanity/form-builder/patch-event'
.And then supposedly firing in an
onAction
handler here;
const handleAction = (field) => {
    const patches = [
      { path: [], type: "setIfMissing", value: [] }, 
      {
        type: "insert",
        items: [{ _type: field.name }],
        path: [-1]
      }
    ]

    PatchEvent.from(patches)
}
But the value is never updated.
AI Update

I can see the issue! You're creating the PatchEvent but not actually calling onChange with it. PatchEvent.from() just creates the action - you need to pass it to the onChange callback that's provided to your custom input component.

Here's what your code should look like:

const handleAction = (field) => {
  const patches = insert(
    [{ _type: field.name }],
    'after',
    [-1]
  )
  const patchEvent = PatchEvent.from(patches).prepend(setIfMissing([]))
  
  onChange(patchEvent) // This is the crucial part!
}

Key points:

  1. You must call onChange - Your custom input component receives an onChange prop from Sanity. You need to invoke it with your PatchEvent for the update to actually happen. As explained in Sanity's PatchEvent documentation, PatchEvent.from() is just an action creator - it doesn't trigger updates on its own.

  2. Use the insert() helper - Instead of manually constructing patch objects with { type: "insert", path: [-1] }, use the insert() helper function. The syntax is insert(items, position, path) where position is 'before' or 'after'.

  3. Chain with prepend(setIfMissing([])) - This ensures the array field exists before trying to insert into it, which prevents errors when the field is initially undefined.

  4. Import the helpers - Make sure you're importing all the necessary functions:

import PatchEvent, { set, unset, setIfMissing, insert } from 'part:@sanity/form-builder/patch-event'

Note on Studio versions: The import you're using (part:@sanity/form-builder/patch-event) is for Sanity Studio v2. If you're on Studio v3, the import path has changed to sanity and the custom input component API is different - you'd use the set() and insert() functions from the sanity package directly.

The pattern shown above follows the documented approach for array insertions in custom components, ensuring your changes properly sync with the Content Lake and work with real-time collaboration.

Show original thread
5 replies
Some additional info that might be useful. I know the event fires because I can log out field. I get no error in Sanity dashboard or the console.
Also, the handler is attached to an imported Sanity dropdown button,
<Button
  kind="simple"
  items={type.of}
  onAction={(field) => handleAction(field)}
  inverted={true}
>
  Add
</Button>
So I figured out why nothing was happening and that because I forgot to wrap the
PatchEvent
in the
onChange
method — 🤦‍♀️. So now I do get an error. My updated PatchEvent looks like this,
onChange(PatchEvent.from(insert({items: [{ _type: field.name, path: [-1] }]})).prepend(setIfMissing([])))
and the new error is,
Cannot read property 'length' of undefined
I’ve made some progress on this. I think I have the patch right (maybe), currently my handler looks like this;
const handleAction = (field) => {
    const patches = insert(
      [{ _type: field.name }],
      'after'
    )
    const patchFrom = PatchEvent.from(patches).prepend(setIfMissing([]))
  
    onChange(patchFrom)
}
My error now is
Attempt to apply insert patch to non-array value
and if I log the
typeof value
it does return
object
.
Hallelujah, I’ve got this working… for a bit anyways. For anyone who is interested this is what my final handler looks like;
const handleAction = (field) => {
    const patches = insert(
      [{ _type: field.name }],
      'after',
      [-1]
    )
    const patchFrom = PatchEvent.from(patches).prepend(setIfMissing([]))
  
    onChange(patchFrom)
  }
The item param will need some work, like a
_key
etc but otherwise this is now inserting an item on to the end of
value
.

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.

Was this answer helpful?