Trouble adding reference to array causing crashes in Sanity UI

6 replies
Last updated: Jun 23, 2023
I’m trying to add a reference to an array and it mostly works fine and then days later it crashes and I can no longer use the component, so i restructured it to match the other object i’m adding to the array and it still seems to crash and I cannot pinpoint the cause of failure. anytime I try and add a reference to the array it searches and then hits me with a :
Error: Objects are not valid as a React child (found: object with keys {$$typeof, render}). If you meant to render a collection of children, use an array instead.
AI Update

This React error typically happens when you're accidentally trying to render a React component object directly instead of using JSX syntax. In the context of Sanity Studio custom components, this often occurs when working with custom input components for reference arrays.

Here are the most common causes and solutions:

1. Check Your Component Return Statement

Make sure you're returning JSX properly. The error suggests you might be returning a component reference instead of rendering it:

// ❌ WRONG - returns component object
const MyComponent = (props) => {
  return props.renderDefault  // This is the component itself
}

// ✅ CORRECT - renders the component
const MyComponent = (props) => {
  return props.renderDefault(props)  // Calling it with props
}

2. Using renderDefault Correctly

When customizing reference array inputs, make sure you're calling renderDefault as a function:

import { defineField } from 'sanity'

export default defineField({
  name: 'myReferences',
  type: 'array',
  of: [{ type: 'reference', to: [{ type: 'someType' }] }],
  components: {
    input: (props) => {
      // Do your custom logic here
      
      // Then render the default component
      return props.renderDefault(props)  // ✅ Called as function
    }
  }
})

3. Check for Async/Promise Issues

If you're fetching data or using useFormValue to access other field values, make sure you're not accidentally returning a Promise:

import { useFormValue } from 'sanity'
import { useEffect, useState } from 'react'

const MyReferenceInput = (props) => {
  const relatedField = useFormValue(['someOtherField'])
  const [isReady, setIsReady] = useState(false)
  
  useEffect(() => {
    // Do async work
    setIsReady(true)
  }, [relatedField])
  
  if (!isReady) return <div>Loading...</div>
  
  return props.renderDefault(props)  // ✅ Returns JSX
}

4. Verify Your Schema Structure

When you say you "restructured it to match the other object," make sure your reference definition is correct:

{
  name: 'myArray',
  type: 'array',
  of: [
    {
      type: 'reference',
      to: [{ type: 'targetDocumentType' }]
      // Not an object with a reference inside
    }
  ]
}

5. Check Component Registration

If you're registering a custom component, ensure you're passing the component correctly:

// ❌ WRONG
components: {
  input: MyComponent()  // Calling it
}

// ✅ CORRECT
components: {
  input: MyComponent  // Passing the component reference
}

Debugging Steps

  1. Add console.logs to see what you're actually returning
  2. Simplify your component to just return props.renderDefault(props) and see if it works
  3. Check the browser console for the full error stack trace - it will show which component is causing the issue
  4. Restart the dev server after schema changes

The "days later it crashes" behavior suggests you might have a conditional that sometimes returns the wrong type, or there's a race condition with async data. Focus on making sure every code path returns valid JSX, not component objects or Promises.

If you can share a minimal version of your custom component code, I can help pinpoint the exact issue!

    defineField({
      name: 'products',
      title: 'Products',
      description: 'Product landings will be pulled automatically unless specified here',
      type: 'array',
      of: [
        {
          type: 'productLandingWithVariant',
        },
        {
          type: 'productBundle',
        }
      ]
    }),
the productlandingwithvariant is fine, I originally had productBundle as an inline object (this is not a graphql build) but i thought that might be why it was failing
so i moved productBundle to:

export default defineField({
  name: 'productBundle',
  title: 'Product Bundle',
  type: 'object',
  icon: TagIcon,
  fields: [
    defineField({
      name: 'bundleProduct',
      type: 'reference',
      to: [{type: 'bundle'}],
      weak: true,
    }),
  ],
  preview: {
    select: {

      title: 'bundle.title',
  
    },
    prepare(selection) {
      const {
        title,
      } = selection

      return {
        title: title,
      }
    },
  },
})
and it still causes the whole sanity ui to crash
lil video where i quickly show it doesn’t crash on the other object that is essentially the same
lol. okay it’s apparently mad at the icon. I think i fixed it finally

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?