Discussion on getting the slug of the most recent blog article for a button in a Navbar component in Next.js using Sanity.io.

26 replies
Last updated: Nov 26, 2021
Now my next question is trying to get the slug of the most recent blog article. I want to create a button that when clicked will always take the user to the most recent blog. Not sure what the query would be for this but so far I have
const query = groq `*[_type == "post"][0]{
    "slug": slug->current
}`;
and in my navbar component I'm passing in props which looks like

const Navbar = (props) => {
    const { slug } = props

    return ( some other code...)
}

AI Update

Your query is close, but there are a couple of issues to fix:

  1. slug->current is incorrect - The slug field is already an object with a current property, so you don't need the -> dereference operator (that's for references). It should be slug.current.

  2. You need to order the results - To get the most recent post, you need to sort by date before taking the first item [0].

Here's the corrected query:

const query = groq`*[_type == "post"] | order(_createdAt desc)[0]{
  "slug": slug.current
}`;

Or if your post schema has a publishedAt or date field (which is more common for blog posts), use that instead:

const query = groq`*[_type == "post"] | order(publishedAt desc)[0]{
  "slug": slug.current
}`;

Breaking it down:

  • *[_type == "post"] - Get all posts
  • | order(publishedAt desc) - Sort by publish date, newest first (the pipe operator chains the ordering operation)
  • [0] - Take the first (most recent) result
  • { "slug": slug.current } - Project just the slug's current value

Then in your Navbar component, you can use it like:

const Navbar = (props) => {
    const { slug } = props;
    
    return (
        <Link href={`/blog/${slug}`}>
            Latest Post
        </Link>
    );
}

Note: Make sure the field you're ordering by (_createdAt, publishedAt, etc.) actually exists in your post schema and has values, otherwise the ordering won't work as expected!

Try:
"slug": slug.current


->
is for resolving references, which I guess isn’t the case here. The slug is an object that looks like this:
{
  slug: {
    current: 'a-slug'
  }
} 

that returns undefined, might be part of the way I'm passing it into my component?
might be. I’d console.log out that you’re at least getting the correct data
Thats what I'm doing, in my component, I'm using console log to log the slug of props and I get Undefined
Is there a better way to achieve what I'm trying?
It’s hard to say if it’s because the data isn’t there or if something happens on the way into the Navbar component. I’d start by confirming that you indeed get all the data you need where you run the
client.fetch
call.
Sorry to ask such amateur questions but how would I do that if my fetch is in an await function?
Navbar.getInitialProps = async function(context) {
    const { slug = "" } = context.query
    return await client.fetch(query, { slug })
}
No worries – we’re all here to learn!
Three things:
1.
getInitialProps
 is considered legacy in Next.js now, you should look at
getServerSideProps
 or `getStaticProps`/`getStaticPaths` instead. Here’s an example with Sanity .2. Is this code that’s located inside of
pages
? The name
Navbar
 hints that it might be a non-page component?3. You can change the code slightly so it’s easier to debug. Note that this will be logged in your terminal (not sure if Next puts it out in the browser as well)

Navbar.getInitialProps = async function(context) {
    const { slug = "" } = context.query
    const post = await client.fetch(query, { slug })
    console.log('post', JSON.stringify(post, null, 2))
    return post
}
(I highly recommend either going through the Learn Next.js docs, or watching Kap’s intro on FreeCodeCamp btw)
okay thanks, the Navbar is just a component piece that I'm sending to my layout so that I can have Navbar on every page without having to write it more than once
There you got it. Only components inside
pages
will actually run the
getInitialProps
function. That’s why you aren’t getting any data from it.
“Global data” has been a pain point with Next.js. They’re working on support for React server components which will make what you’re trying to do work.
Oh interesting, good to know. So this isnt really possible in a component the way I'm trying to do it. Unless of course I write the navbar on every page
Also 1 other question if I need to use getServerSideProps this tutorial is out of date and I'd have to do
return {
return {
   props: {
      title: post.title,
      body: post.body,
      image: post.mainImage
   }
}
yeah, we should really update that guide. And yes, you need to return the data under the
props
key 👍
lol thats what I had then the other night someone told me to use the updated version of sanity/next relation so I thought following a guide from you would be better than YouTube, oh well haha
I’ll start by adding a disclaimer to the guide 😅
Okay haha now I'm real confused because I was using
const url = `https://.<http://api.sanity.io/v1/data/query/production?query=${query}`;|api.sanity.io/v1/data/query/production?query=${query}`;>

const result = await fetch(url).then(res => res.json());
const post = result.result[0];
Should I still use this just with my new query?
I’d replace this with
client.fetch
like you have in earlier code snippet you pasted
gotcha thank you
but what props would I return because I was using the const post for post.title
Not sure what context you’re in 🙂
lol all good I'll keep working thanks for the help
I’ve updated the guide to use
getStaticProps
 and
getStaticPaths
 now 🙂
haha great thank you

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?