Access array index in custom input component with withDocument HOC

2 replies
Last updated: Dec 22, 2021
Hi! I'd like to get value's from the parent component of my custom input component. However I get stuck at the withDocument HOC, because I'm using the custom input component in an array of which I want the index in my custom input.
{
  name: "filters",
  title: "Filters",
  type: "array",
  of: [
    {
      type: "object",
      name: "category",
      fields: [
        {
          type: "reference",
          name: "category",
          to: [{ type: "category" }],
        },
        {
          name: "productFilters",
          type: "string",
          inputComponent: ProductFilter,
        },
      ],
    },
  ],
}
AI Update

I can help you access parent values and the array index in your custom input component! First, I need to correct the schema definition - in Sanity Studio v3, you need to use components: { input: ProductFilter } instead of inputComponent.

Corrected Schema Definition

{
  name: "filters",
  title: "Filters",
  type: "array",
  of: [
    {
      type: "object",
      name: "category",
      fields: [
        {
          type: "reference",
          name: "category",
          to: [{ type: "category" }],
        },
        {
          name: "productFilters",
          type: "string",
          components: {
            input: ProductFilter  // ✅ Correct syntax for Studio v3
          }
        },
      ],
    },
  ],
}

Accessing Array Index and Parent Values

The modern approach (replacing the deprecated withDocument HOC) is to use the path prop and the useFormValue() hook. Every custom input component receives a path prop that contains an array describing the field's location in the document, including the _key of array items.

Here's how to access both the array index and parent values:

import { useFormValue } from 'sanity'

const ProductFilter = (props) => {
  const { path, value, onChange } = props
  
  // The path will look like: ['filters', {_key: 'some-key'}, 'productFilters']
  // Extract the _key from the path
  const arrayItemKey = path.find(segment => segment._key)?._key
  
  // Get the full filters array from the document
  const filtersArray = useFormValue(['filters'])
  
  // Find the index of this item in the array
  const currentIndex = filtersArray?.findIndex(item => item._key === arrayItemKey) ?? -1
  
  // Access the parent category reference for this specific array item
  const parentCategory = useFormValue([...path.slice(0, -1), 'category'])
  
  return (
    <div>
      <p>Current array index: {currentIndex}</p>
      <p>Parent category reference: {parentCategory?._ref}</p>
      {/* Your custom input logic here */}
    </div>
  )
}

Alternative Approach: Using Parent Object

You can also get the parent object directly by slicing the path:

import { useFormValue } from 'sanity'

const ProductFilter = (props) => {
  const { path, value, onChange } = props
  
  // Get the parent object (the array item) by removing the last path segment
  const parentObject = useFormValue(path.slice(0, -1))
  
  // Get array item key from path
  const arrayItemKey = path.find(segment => segment._key)?._key
  
  // Get the filters array
  const filtersArray = useFormValue(['filters'])
  
  // Calculate the current index
  const currentIndex = filtersArray?.findIndex(item => item._key === arrayItemKey) ?? -1
  
  // Access the category reference from the parent object
  const categoryRef = parentObject?.category
  
  return (
    <div>
      <h3>Product Filter #{currentIndex + 1}</h3>
      <p>Category ID: {categoryRef?._ref}</p>
      <input 
        type="text" 
        value={value || ''} 
        onChange={(e) => onChange(e.target.value)}
      />
    </div>
  )
}

export default ProductFilter

Key Points

  1. props.path gives you the breadcrumb trail to your field, including the _key of array items
  2. useFormValue(path.slice(0, -1)) gives you the parent object by removing the last path segment
  3. You can find the array index by comparing the _key from your path with all items in the array using findIndex()
  4. useFormValue() replaces the deprecated withDocument HOC and gives you access to any value in the document
  5. Use useFormValue([]) to access the entire document if needed

This approach works perfectly for nested objects inside arrays and gives you full access to parent values without needing the old HOC pattern!

Show original thread
2 replies
In your case, you'd be able to find the index of the parent
category
object inside of the
filters
array using the
withDocument
HOC like so:
const index = props.document.filters.indexOf(parent)
Does this component need to be reused in other places though? If so, we'd need to figure out a more flexible way of accessing it!
Thanks! This is what I needed

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?