Joint session with Vercel: How to build intelligent storefronts (May 15th)

useState setter not working in useEffect with async API call

25 repliesLast updated: Nov 29, 2025

Im creating a custom api calling input however the useState setter is not working inside useEffect async api call. Sorry for the long winded code message. Here’s my code if someone can assist:
const AsyncSelect = React.forwardRef((props, ref) => {
  const [sessions, setSessions] = useState([])

  const {
    type,         // Schema information
    value,        // Current field value
    readOnly,     // Boolean if field is not editable
	placeholder,
    markers,      // Markers including validation rules
    presence,     // Presence information for collaborative avatars
    compareValue, // Value to check for "edited" functionality
    onFocus,      // Method to handle focus state
    onBlur,       // Method to handle blur state
    onChange      // Method to handle patch events
  } = props

  // Creates a change handler for patching data
  const handleChange = React.useCallback(
    // useCallback will help with performance
    (event) => {
      const inputValue = event.currentTarget.value // get current value
      // if the value exists, set the data, if not, unset the data
      onChange(PatchEvent.from(inputValue ? set(inputValue) : unset()))
    },
    [onChange]
  )

  const inputId = useId()


	useEffect(() => {
		const getSessions = async () => {

			const data = await fetch("<https://api.call>")

			const json = await data.json()

            const tSessions = await setSessions(json.collection) //NOT WORKING!!!

    }
		getSessions()
    	.catch(console.error);
  }, [])

	return (
    &lt;FormField
      description={type.description}  // Creates description from schema
      title={type.title}              // Creates label from schema title
      __unstable_markers={markers}    // Handles all markers including validation
      __unstable_presence={presence}  // Handles presence avatars
      compareValue={compareValue}     // Handles "edited" status
      inputId={inputId}               // Allows the label to connect to the input field
    &gt;
      &lt;Card padding={0}&gt;
        &lt;Stack&gt;
          &lt;Select
            id={inputId}                  // A unique ID for this input
            fontSize={2}
            padding={[3, 3, 4]}
            space={[3, 3, 4]}
            value={value}                 // Current field value
            readOnly={readOnly}           // If "readOnly" is defined make this field read only
            onFocus={onFocus}             // Handles focus events
            onBlur={onBlur}               // Handles blur events
            ref={ref}
            onChange={handleChange}       // A function to call when the input value changes
          &gt;
            &lt;option value={''}&gt;---&lt;/option&gt;
            {sessions.map((s) =&gt; ({ s.name})
          &lt;/Select&gt;
        &lt;/Stack&gt;
      &lt;/Card&gt;
    &lt;/FormField&gt;
	)
})

export default AsyncSelect
AI Update

This is a common React issue, not specifically a Sanity problem, but I can help! The issue is that setSessions is a state setter function, not an async function - it doesn't return a promise, so you shouldn't await it.

Here's the corrected code:

useEffect(() => {
  const getSessions = async () => {
    const data = await fetch("https://api.call")
    const json = await data.json()
    
    setSessions(json.collection) // Remove the await here!
  }
  
  getSessions().catch(console.error);
}, [])

Why this happens:

Additional improvements for your code:

{sessions.map((s) => (
  <option key={s.id || s.name} value={s.name}>
    {s.name}
  </option>
))}
const [sessions, setSessions] = useState([])
const [loading, setLoading] = useState(true)

useEffect(() => {
  const getSessions = async () => {
    try {
      const data = await fetch("https://api.call")
      const json = await data.json()
      setSessions(json.collection)
    } catch (error) {
      console.error(error)
    } finally {
      setLoading(false)
    }
  }
  
  getSessions()
}, [])

The main fix is removing await from setSessions - that should get your component working!

Show original thread
25 replies

Was this answer helpful?

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.

Related contributions