Fetch correct data in getStaticProps in preview mode

Hello prismic people.

Im having some difficulties setting up previews with prismic and nextjs. My problem is that when i do hit the preview api endpoint, the redirect work and a ref for the preview are being passed to getStaticProps.

In getStaticProps im able to fetch the preview data by passing the ref to the client options ( is this the prefered way? the nextjs part of the prismic docs say nothing about how to do this btw)

But all my other calls with the client, that are supposed to return data from the master ref(my hope is) doesn't return anything.

The other calls i make are for global stuff like the header and footer components, so they are never in a preview-state. Do all calls via the client use the new ref in some way or is it possible to make these requests still work in preview mode?

I've tried setting the query options ref to the master ref when in preview on those other calls but it didn't make a difference, example below:

const api = await client.getApi()
const global = (await client.getSingle('global_layout', { lang: locale, ref:  })) || {}
const allPosts = (await client.query(Prismic.Predicates.at('document.type', 'blog_post'), { lang: locale, ref: api.data.masterRef.ref })) || {}

My client:

const apiEndpoint = 'https://myproject.cdn.prismic.io/api/v2'
export const client = Prismic.client(apiEndpoint)

My preview endpoint (nevermind the linkresolver, its temporarly and not the problem :):

import { client } from 'lib/prismic/client'
import { linkResolver } from 'lib/prismic/link-resolver'

export default async function preview(req, res) {
    const { token: ref, documentId } = req.query
    const url = await client.getPreviewResolver(ref, documentId).resolve(linkResolver({type: 'blog_post', uid: '/news/vinden-levererar-till-din-dorr'}), '/news/vinden-levererar-till-din-dorr')
  
    if (!url) {
      return res.status(401).json({ message: 'Invalid token' })
    }
  
    res.setPreviewData({
      ref, // pass the ref to pages so that they can fetch the draft ref
    })


    res.write(
      `<!DOCTYPE html><html><head><meta http-equiv="Refresh" content="0; url=${url}" />
      <script>window.location.href = '${url}'</script>
      </head>`
    )
  
    res.end()
  }

getStaticProps:

export async function getStaticProps({ params, locale, preview = false, previewData }) {
  let posts
  if (preview) {
    const { ref } = previewData
    posts = (await client.getByUID('blog_post', params.uid, { ref })) || {}
  } else {
    posts = (await client.getByUID('blog_post', params.uid, { lang: locale })) || {}
  }
  const global = (await client.getSingle('global_layout', { lang: locale })) || {}
  const allPosts = (await client.query(Prismic.Predicates.at('document.type', 'blog_post'), { lang: locale })) || {}

  return {
    props: {
      posts,
      global,
      allPosts,
    },
  }
}

Hope someone knows what could be the problem since that would make my day!
/ Hugo

Hi Hugo,

Welcome to the community! I'll be happy to help.

The first thing I would say is there is no need to set the ref to master ref as this is done automatically for you. Also, even though you said it's temporary, there's no need to pass the linkresolver configuration to the function as you've done here.

In your getStaticProps query, you don't need to do anything special for previews as you have done here, everything should be handle for you the code in the api/preview.js which you showed above. Also, I'm not sure where you're doing the query you've shown here but you would be able to do a getByUID query and hope that it works alongside a 'get all posts' query as you've done above.

So, let's say you've done a query on a dynamic [uid].js page for one post, then you should configure your page like so:

export async function getStaticProps({ params, locale, previewData }) {
  const ref = previewData ? previewData.ref : null
  const global = (await client.getSingle('global_layout', ref ? { ref, lang: locale } : { lang: locale })) || {}
  const post = (await client.getByUID('blog_post', params.uid, ref ? { ref, lang: locale } : { lang: locale })) || {}
  return {
    props: {
      preview: ref,
      global,
      post
    }
  }
}

export async function getStaticPaths() {
  const documents = await queryRepeatableDocuments((doc) => doc.type === 'blog_post')
  return {
    paths: documents.map(doc => `/blog/${doc.uid}`),
    fallback: true,
  }
}

As we do in our blog example. You set the preview data as empty for a normal query, then the api/preview route code enables preview mode and loads the data in this empty object for you. So make sure when you set this preview route correctly in your Prismic repo.

I release now the preview document could be clearer and I will work on that. We are also working on making previews easier to implement for Next.js.

Thanks.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.