简体   繁体   中英

Reasoning with _raw and normal data in Gatsby, GraphQL and Sanity

I've just started using Gatsby with the Sanity headless CMS.

For the most part it's pretty straight forward; but knowing best practises for querying the data through GraphQL is still bothering me. How I'm doing it currently is just frantically clicking through my CMS structure in the GraphQL playground and finding what I want. This works but the lack of uniformity in this approach is making me uneasy.

For example, if I want a hero image that's in the CMS somewhere, i'll need to do something like:

query SomePageQuery($id: String) {
  sanitySomePage(id: { eq: $id }) {
    id
    heroImage {
      asset {
        fluid(maxWidth: 1500) {
          ...GatsbySanityImageFluid
        }
      }
    }
  }
}

But if I want some PortableText block then I need to query the corresponding _raw field of whatever type. So, if my type was introText , Gatsby also provides a _rawIntroText . I'm only able to get the full PortableText from this _raw version of the data. Like this:

query SomePageQuery($id: String) {
  sanitySomePage(id: { eq: $id }) {
    id
    _rawIntroText
  }
}

It seems that, for some data you can use [Type] , and sometimes you have to use _raw[Type] .

There's not a great deal of documentation as to why this is the case. And I'm not sure if this is enforced via Sanity or Gatsby.

My question I guess would be, why does _raw[Anything] exist in the Gatsby and/or Sanity world, and how do people decide on which to use (other than just trial and error within the GraphQL playground and at runtime)?

This is coming from the gatsby-source-sanity plugin that Sanity built and maintains. Hopefully someone from Sanity can provide more context, but effectively the _raw[FieldName] entries return the original JSON data for the field. The unprefixed field (eg fieldName ) is probably not what you want—it'll only contain bits of metadata about the data.

I tend to pull the _raw[FieldName] data and then just pass it straight into the @sanity/block-content-to-react component like so:

import React from "react"
import { graphql } from "gatsby"
import SanityBlockContent from "@sanity/block-content-to-react"

export default ({ data: { page } }) => (
  <SanityBlockContent
    blocks={page.textContent}
    projectId={process.env.GATSBY_SANITY_PROJECT_ID}
    dataset={process.env.GATSBY_SANITY_DATASET}
  />
)

export const query = graphql`
  query SomePageQuery($id: String) {
    page: sanitySomePage(id: { eq: $id }) {
      textContent: _rawTextContent
    }
  }
`

Note that I'm using GraphQL aliasing to continue to refer to the field as textContent in my component rather than coupling the component to the specifics of this GraphQL schema.

You don't need to use Gatsby Image for Sanity images since they have their own image transformation pipeline anyways. Instead you can just fetch asset { _id } and then use @sanity/client like this to generate an image url:

import sanityClient from "@sanity/client"
import sanityImageUrl from "@sanity/image-url"

const client = sanityClient({
  dataset: process.env.GATSBY_SANITY_DATASET,
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  useCdn: true,
})

const builder = sanityImageUrl(client)

builder.image({ _id: "..." }).width(400).dpr(2).url()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM