Building custom input component with expanding list causing issues

1 replies
Last updated: Jun 1, 2023
I'm building a custom input component for a string where I use
props.renderDefault
and I expand the list in the options, since I expand the list by using:
props.schemaType.options = {...props.schemaType.options, list: [...list, ...myList]}
the list in the field keeps getting bigger, looks like that in each render the list I get is the list after it was already expanded (no the original list from 'options')
How can I fix that?
AI Update

The issue you're experiencing is that you're mutating the props.schemaType.options object directly, which causes the list to accumulate on every render. In React, props should be treated as immutable, and schemaType is a shared object reference that persists across renders.

When you do:

props.schemaType.options = {...props.schemaType.options, list: [...list, ...myList]}

You're modifying the actual schema type object, so each render adds to the already-modified list rather than the original one.

Solution

Create a new local options object instead of mutating the original. Here's how to fix it:

export function CustomStringInput(props: StringInputProps) {
  // Create a new schemaType with expanded options without mutating the original
  const expandedSchemaType = {
    ...props.schemaType,
    options: {
      ...props.schemaType.options,
      list: [...(props.schemaType.options?.list || []), ...myList]
    }
  }

  // Pass the new schemaType to renderDefault
  return props.renderDefault({
    ...props,
    schemaType: expandedSchemaType
  })
}

Key Points

  1. Never mutate props directly - Always create new objects when you need to modify data
  2. Create the expanded options in the render - This ensures you start from the original schema definition each time
  3. Pass the modified props to renderDefault - The renderDefault function accepts props as an argument, so you can pass your modified version

This approach ensures that each render starts with the original props.schemaType.options.list from your schema definition, then adds your custom items on top, rather than continuously appending to an ever-growing list.

Well, I guess this solves it and I shouldn't assign to options directly
 return props.renderDefault({
    ...props,
    schemaType: {
      ...props.schemaType,
      options: {...props.schemaType.options, list: [...list, ...myList]},
    },
  })

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?