👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

Troubleshooting image rendering in Sanity.io, with guidance on resolving asset references and using @portabletext/react.

65 replies
Last updated: May 13, 2022
Hey all, I'm having a hard time making the images from my markdown/blockcontent render. I'm getting the following error (see screenshot). I'll attach snippets of my groq query and schema as well. Any guidance would be very helpful, I visited the Sanity "Block content image materializing" docs page but I'm still confused about how to integrate this properly.
Thanks in advance!
May 13, 2022, 1:52 PM
What you’ve done looks good from what I can see. I’ve never encountered that error before, that’s odd.
May 13, 2022, 1:53 PM
For some reason it won't let me edit my original message with my schema, but yeah -- any ideas on what I can try here?
May 13, 2022, 1:54 PM
Here's the query
May 13, 2022, 1:55 PM
The "image" type at the very bottom appears just fine, but the image [7] in the "description" field doesn't render
May 13, 2022, 1:56 PM
The error in my console links to this article: https://www.sanity.io/help/block-content-image-materializing
May 13, 2022, 1:56 PM
Ah yes of course!
May 13, 2022, 1:58 PM
You need to resolve its reference.
description[] {
  ...,
  _type == "image" => {
    "image": asset->url
  )
}
May 13, 2022, 1:58 PM
Also, when I hit "copy url" here i'm able to visit the url
May 13, 2022, 1:59 PM
Oh I see, could you maybe help me understand what is happening in that block of code you sent?
May 13, 2022, 1:59 PM
and do you mean the query should be structured like so?
Edit: I'm missing a } at the end there
May 13, 2022, 2:00 PM
Right. So your
description
field is portable text. It’s an array of blocks. References are not automatically resolved in portable text, you have to do that yourself.
May 13, 2022, 2:00 PM
Hm, interesting
May 13, 2022, 2:01 PM
import groq from "groq";

export const eventDescriptionQuery = groq`
*[_type=="eventDescription"]{
    name,
    description,
    launchAt, 
    endAt,
    location,
    "id": _id,
    _type == "image" => {
    "image": asset->url
  }
  }`;
May 13, 2022, 2:01 PM
hm so with the above code, i'm still getting that same error unfortunately
May 13, 2022, 2:03 PM
So instead of just querying
description
like you did, we make that a bit more specific.
The brackets here mean we’re going to loop over its content.

description[] { <more stuff here> }
The dots here mean “query everything”, which is what your version does so far (still no references):

description[] {
  ...,
  <more stuff here>
}
The rocket (
=>
) is a condition. Here we say “do that bit when the block type is `image`”:
description[] {
  ...,
  _type == "image" => {
    <more stuff here>
  }
}
Finally, we resolve the asset reference to find the URL and assign it to an
image
property:
description[] {
  ...,
  _type == "image" => {
    "image": asset->url
  }
}
May 13, 2022, 2:03 PM
When you say "references", you mean the fields I enter into the schema, right? just want to make sure I understand
May 13, 2022, 2:05 PM
A reference is what happens when you link a different document or an image. When you add an image to your portable text, it creates a reference to an asset object. It doesn’t actually embed the image details right there.
May 13, 2022, 2:05 PM
I see! That makes sense
May 13, 2022, 2:07 PM
So you need to “resolve” that asset reference. This is what the arrow (
->
) does in a query. This is what you already do for your image field.
May 13, 2022, 2:07 PM
import groq from "groq";

`export
const eventDescriptionQuery = groq``
*[_type=="eventDescription"]{

name,

description[] {

...,

_type == "image" => {

"image": asset->url

}

}

launchAt,

endAt,

location,

"id": _id,

"image": image.asset->url,
`}`;`
May 13, 2022, 2:07 PM
so like this then?
May 13, 2022, 2:07 PM
But you also need to do the same for images that you’ve embedded in your portable text, in a similar fashion.
May 13, 2022, 2:07 PM
Yes, precisely. 🙂
May 13, 2022, 2:07 PM
Strange though, because i'm now getting the following:
May 13, 2022, 2:07 PM
Your groq query is invalid, you missed a comma.
May 13, 2022, 2:08 PM
omg lol oops, good catch!
May 13, 2022, 2:08 PM
err but i'm back to getting the original error now
May 13, 2022, 2:08 PM
I’m not sure how you render your portable text, but you’ll need to give a renderer to image blocks.
May 13, 2022, 2:09 PM
this is how I render the content
May 13, 2022, 2:11 PM
What is
BlockContent
?
May 13, 2022, 2:12 PM
it's how I render the markdown
May 13, 2022, 2:16 PM
to be completely honest I don't remember how or where I got the snippet from lol
May 13, 2022, 2:16 PM
but I import it as follows:

import BlockContent from "@sanity/block-content-to-react";
May 13, 2022, 2:16 PM
Alright.
May 13, 2022, 2:17 PM
This is the old library, and I believe it is deprecated. You should migrate to @portabletext/react .
May 13, 2022, 2:17 PM
The API is similar, and there is a guide for going from one lib to the other, so it should be relatively straightforward.
May 13, 2022, 2:18 PM
sweet, i'll look into this!
May 13, 2022, 2:20 PM
So one small question
May 13, 2022, 2:21 PM
May 13, 2022, 2:22 PM
do I install this into the Studio (sanity) or Web (src) side of things?
May 13, 2022, 2:22 PM
or globally?
May 13, 2022, 2:22 PM
Definitely on your frontend. This is part of your rendering layer, so it’s not related to the studio. 🙂
May 13, 2022, 2:23 PM
Hey so, I installed @portabletext/react, and i'm able to access my webpage with no errors, but the image still isn't appearing. I'm getting the following in my console:
May 13, 2022, 2:34 PM
Here's how I reference portabletext:
May 13, 2022, 2:35 PM
You’re not going to need
@sanity/image-url
, because we resolve the references manually in the query. It’s either one or the other.
May 13, 2022, 2:36 PM
With the query we authored together, your image component should receive the image URL as
value.image
. Maybe try that (or
console.log(value)
so we see what’s in therE.)
May 13, 2022, 2:36 PM
within my
sanityImageComponent
you mean?
May 13, 2022, 2:36 PM
Yes.
May 13, 2022, 2:37 PM
it worked!! I'm seeing the image now !! 🎉
May 13, 2022, 2:38 PM
Lovely. 💖
May 13, 2022, 2:38 PM
Although it's rendering in full size, if I wanted to add styling i'm assuming I should manipulate the style of &lt;img&gt; within SanityImageComponent?
May 13, 2022, 2:38 PM
Is there an "ideal" way to do this?
May 13, 2022, 2:38 PM
If you need the image dimensions, we can also query them as part of our query.
_type == "image" => {
  "image": asset->url,
  "dimensions": {
    "width": image.asset -> metadata.dimensions.width,
    "height": image.asset -> metadata.dimensions.height,
    "aspectRatio": image.asset -> metadata.dimensions.aspectRatio,
  }
}
May 13, 2022, 2:39 PM
(Considering you’re getting the dimensions to compute the aspect ratio, you could also query only the aspect ratio from Sanity, as shown above.)
May 13, 2022, 2:40 PM
Although it's rendering in full size, if I wanted to add styling i'm assuming I should manipulate the style of &lt;img&gt; within SanityImageComponent?
Yes, styling is up to you. Depends what you want to achieve. 🙂
May 13, 2022, 2:40 PM
Oh great 🙂 Thank you so much for your help!! You've been awesome
May 13, 2022, 2:40 PM
You could also add some options on the Sanity side, so when you add an image to the portable text, you can configure it with custom settings. You can then query these settings and use them to define styles.
May 13, 2022, 2:41 PM
How do you mean exactly? Do you have a docs reference for this by chance?
May 13, 2022, 2:42 PM
Right now you have this in your schema:
{
  type: "image",
  options: { hotspot: true }
}
You could do something like:

{
  type: "image",
  options: { hotspot: true },
  fields: [
    { title: 'Full width', name: 'isFullWidth', type: 'boolean', defaultValue: false }
  ]
}
Then you query that part:

_type == "image" => {
  isFullWidth,
  "image": asset->url,
  "dimensions": {
    "width": image.asset -> metadata.dimensions.width,
    "height": image.asset -> metadata.dimensions.height,
    "aspectRatio": image.asset -> metadata.dimensions.aspectRatio,
  }
}
And then in your component, you use
value.isFullWidth
to set specific styles or something.
May 13, 2022, 2:44 PM
This is just an example of course. You could have any sort of field to configure how your image gets rendered.
May 13, 2022, 2:44 PM
woah, that's so cool
May 13, 2022, 2:45 PM
it's really nice to see how flexible Sanity is coming off of using other CMS in the past
May 13, 2022, 2:45 PM
For real. 😊
May 13, 2022, 2:45 PM
thank you so much for your help :)
May 13, 2022, 2:47 PM
Of course. 💖
May 13, 2022, 2:49 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?