Sanity client.listen() not working - "listen is not a function" error

4 replies
Last updated: Jun 20, 2023
I try to run client.listen() but I get the error “listen is not a function”
Here is the code :


/*
composable for loading and previewing data from sanity 
*/
export default async function ({ query, params, livePreview = true }) {
	const mainStore = useMainStore()
	const sanityClient = mainStore.previewIsActive
		? {
				client: 'preview',
				server: false,
				initialCache: false,
		  }
		: undefined

	// live preview: listen to changes
	onMounted(() => {
		if (mainStore.previewIsActive && livePreview) {
			const sanity = useSanity('preview')
			console.log('rr')
			
			sanity.client.listen(query, params).subscribe((event) => {
				setTimeout(() => {
					refresh()
				}, 900)
			})
		}
	})

	// get data
	const { data, refresh } = await useLazySanityQuery(
		query,
		params,
		sanityClient
	)

	return data
}
Do you know why he tells me that
listen
is not a function?
Thank you
AI Update

The error you're seeing - "listen is not a function" - is happening because the @nuxtjs/sanity module creates a minimal client by default, and the minimal client doesn't include the listen() method.

The minimal client (similar to picosanity) is designed specifically for fetching content only - it has a smaller bundle size but lacks mutation and real-time listening capabilities.

Solution: Use the full Sanity client

You need to install and use the full @sanity/client package instead of relying on the client from useSanity(). Here's how to fix your code:

// Install the full client
// npm install @sanity/client

import { createClient } from '@sanity/client'
import { useMainStore } from '~/stores/main'

export default async function ({ query, params, livePreview = true }) {
  const mainStore = useMainStore()
  const sanityClient = mainStore.previewIsActive
    ? {
        client: 'preview',
        server: false,
        initialCache: false,
      }
    : undefined

  // Create a full client instance with listen() support
  const previewClient = createClient({
    projectId: 'your-project-id',
    dataset: 'your-dataset-name',
    useCdn: false, // Important for preview/draft content
    apiVersion: '2025-02-06',
    token: process.env.SANITY_TOKEN, // Required for preview mode
    perspective: 'previewDrafts' // To see draft content
  })

  // live preview: listen to changes
  onMounted(() => {
    if (mainStore.previewIsActive && livePreview) {
      previewClient.listen(query, params).subscribe((event) => {
        setTimeout(() => {
          refresh()
        }, 900)
      })
    }
  })

  // get data using the Nuxt composable
  const { data, refresh } = await useLazySanityQuery(
    query,
    params,
    sanityClient
  )

  return data
}

Modern Alternative: Consider the Live Content API

If you're building a modern Nuxt app, you might want to consider using Sanity's Live Content API instead of listen(). It provides real-time updates without websockets and works seamlessly with Nuxt through framework loaders. This is the recommended approach for new projects as it handles caching and updates more efficiently.

The key takeaway: the useSanity('preview') composable from @nuxtjs/sanity gives you a minimal client that can't listen to real-time changes. You need the full @sanity/client for that functionality.

Show original thread
4 replies
I don’t have an answer, but am providing the source for context since most of these are custom hooks.
Have you pinned the client to the same version as the lock file of the template?
Thank you. @sanity/client wasn’t installed
Glad you’re up and running! 🎉
user Q
i installed @sanity/client but doesn't work for me. Do you have any recomendation?

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?