LiveQueryProvider error in Next.js 14.0.4 with next-sanity@7.0.3

2 replies
Last updated: Dec 12, 2023
Hi folks, I have an issue with the
LiveQueryProvider
in latest Next.js 14.0.4 with
next-sanity@7.0.3
. If I comment out the Provider everything works fine but with the Provider enabled I get the following error message

Error: Element type is invalid. Received a promise that resolves to: [object Object]. Lazy element type must resolve to a class or function. Did you wrap a component in React.lazy() more than once?
Does anyone else have the same issue?
AI Update

This error typically occurs when you're using LiveQueryProvider in a Next.js App Router environment. The "Element type is invalid. Received a promise that resolves to: [object Object]" error is React's way of telling you that a component is being treated as an async function when it shouldn't be.

The Root Cause

The issue is likely that LiveQueryProvider is being imported or used in a way that conflicts with Next.js 14's Server Components architecture. In Next.js 14 with the App Router, components are Server Components by default, and client-side providers need to be explicitly marked with 'use client'.

Modern Solution: Use the Live Content API

The good news is that LiveQueryProvider is actually part of an older preview approach. The modern, recommended way to handle live content updates in next-sanity is using the Live Content API with defineLive and SanityLive.

Here's how to migrate to the modern approach:

1. Set up defineLive

Create a file to configure your live content setup:

// sanity/lib/live.ts
import { createClient } from 'next-sanity'
import { defineLive } from 'next-sanity'

const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
  apiVersion: '2024-01-01',
  useCdn: true,
  stega: { studioUrl: '/studio' },
})

export const { sanityFetch, SanityLive } = defineLive({
  client,
  serverToken: process.env.SANITY_API_READ_TOKEN,
  browserToken: process.env.NEXT_PUBLIC_SANITY_API_READ_TOKEN,
})

2. Add SanityLive to your layout

The SanityLive component handles live updates and must be added to your root layout:

// app/layout.tsx
import { SanityLive } from '@/sanity/lib/live'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <SanityLive />
      </body>
    </html>
  )
}

3. Use sanityFetch in your components

Replace your existing data fetching with sanityFetch:

// app/page.tsx
import { sanityFetch } from '@/sanity/lib/live'

export default async function Page() {
  const { data } = await sanityFetch({
    query: `*[_type == "post"]{ title, slug }`,
  })
  
  return <div>{/* render your content */}</div>
}

If You Need to Stick with LiveQueryProvider

If you absolutely need to continue using LiveQueryProvider with version 7.0.3, make sure:

  1. Mark it as a client component - Create a wrapper component with 'use client' at the top:
// components/LiveQueryProviderWrapper.tsx
'use client'

import { LiveQueryProvider } from '@sanity/preview-kit'

export default function LiveQueryProviderWrapper({ children, client }) {
  return (
    <LiveQueryProvider client={client}>
      {children}
    </LiveQueryProvider>
  )
}
  1. Import it correctly - Make sure you're importing from the right package (@sanity/preview-kit not next-sanity)

However, I strongly recommend migrating to the modern Live Content API approach as it's designed specifically for Next.js 14's architecture, provides better performance, and is the actively maintained solution going forward.

Show original thread
2 replies
Got it,
@sanity/preview-kit
already wraps the
LiveQueryProvider
in a lazy import. So importing the component without
dynamic
works.
Thanks πŸ™

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?