Astro image query Issue

Hello Roger / Support,

Everything was good in the world and I believed my query issues were resolved but there was a cruel twist when I ran a build! :slightly_smiling_face:

Everything is ok on my local version when I use ‘switch(section._modelApiKey)’ but I get a build error of ‘Cannot read properties of undefined (reading ‘url’)’ for one of the pages.

I found the line of code in question it’s the image component on line 172 (see link)

I tried using the ‘switch(section._modelApiKey)’ on it ('cannot find name ‘sections’ error) but as you can see that file is slightly different as it uses a ‘getStaticPaths’ to dynamically generate pages. This means I’m accessing all of the query data using ‘post’ and bracket notation.

Sorry to open a new ticket but any advice would be greatly appreciated!

Thanks,

Richard Gill

Hmm, it seems to work for me using your same code?

Did you remember to set the DATOCMS_API_KEY in your env vars / .env file? What is the output of post (or the sections object before it)… i.e. are you sure you’re getting back a valid GraphQL response, or is there maybe some error in the fetch…? You can use the Astro troubleshooting tips to try and see when the code starts breaking: Troubleshooting | Docs (or just step through it in the debugger in your IDE)

Example:
(I had to comment out BaseLayout and the BackArrow image though, since I don’t have them, but otherwise this is just your code with an API key in the env var. That’s not shared, don’t worry):

(Products 1 to 8 should work too if you change the URL)

If setting the envar doesn’t fix it, can you share the whole repo with me (r.tuan@datocms.com on Github) and the first four characters of the API key you’re using so I can take a more detailed look? The code you have seems OK to me, so maybe the problem is elsewhere?


Never worry about this! You’re always welcome to ask more questions :slight_smile:

Hello Roger,

Thanks for the detailed response but I’ve hit a brick wall on this one.

When I created the ‘Hire’ section (see Limelight Event Services | Hire), I cloned the
‘index.astro’ and ‘slug.[astro]’ from the already working projects page (Limelight Event Services | Projects) which essentially does the same sort of thing - i.e show a list of mapped over elements and dynamically create pages out of them using the slug.

The first sign I had of things not being right was a ‘Expected “slug” to be a string’ error (line 45 of [slug].astro in the hire folder) so I changed it from;

‘params: { slug: post.slug }’

to ‘params: { slug: String(post.slug)}’

This works, but I thought I better mention it in case this is causing the error in some way.

I’ve also commented out my last attempt on line 177 of [slug].astro. This should work but ‘sections’ is no longer available to map over as the ‘sections.map’ function on line 43 changes ‘sections’ to ‘posts’ - nightmare!

I’ve upload the files in question to the repo - GitHub - albionCircus/datocms

I also checked the api key etc in the env file which all looks good.

It’s so frustrating as it works locally which in some ways makes it harder to debug!

Thanks in advance,

Richard Gill

Ahhh, wait a minute, I’m sorry, I got confused about what you were trying to accomplish. I thought you were trying to map through sections on a single page. But looking at the code again, I think you’re trying to make individual pages (using getStaticPaths()) out of a modular content field (sections)?

e.g. /hire/product-1, /hire-product-2, etc?

You can do that, but it’s a bit non-standard to use a modular content field that way. Usually, each product would instead be a standalond record in a separate “Products” model, then you can generate all the product pages easily with a GraphQL query like:

allProducts {
    id
    slug
}

If you want to keep them as blocks inside a MCF, my suggestion is to keep that “Sections” field limited to one type of block only (the “Product”), and move the “Hero Banner” into its own separate set of fields in the Hire page.

Then, in /hire/index.astro you can read all the stuff needed just for the /hire page. And in /hire/[slug].astro, you can fetch the sections and use that only to generate the products pages (like /hire/product-1).

Right now, I think you’re getting that error because Astro is encountering the Hero Banner block, which has no slug, and it’s trying to generate a product page from that.

Essentially, you’ve combined two schemas into one, and it’s confusing Astro (and me! :slight_smile:)

Once you clean that up, you don’t need to map through sections again within each product page, because each product page IS already a post at that point. You wouldn’t map through its images again, which isn’t an array, you’d just use post.image.url or whatever.


But again, I think it would be clearer just to make Products their own separate model, and query them separately apart from your regular pages. The Modular Content Field is better-suited for creating, well, sections on a page rather than generating individual pages. Not really for any technical reason, just for mental clarity. That way, you can better distinguish when you’re querying a page for its own content & sections vs when you’re trying to enumerate records to build URLs from (like for products).

Thanks so much Roger, I got it working!
I restructured the products into standalone records which is much cleaner. I think I was getting carried away building everything in blocks which made the querying unnecessarily complex.
Thanks again, onwards and upwards!

1 Like

Great, glad that worked!

I think I was getting carried away building everything in blocks which made the querying unnecessarily complex.

I think we can also do a better job of explaining when to use linked records vs blocks. That’s actually part of some documentation updates I’m working on. If you have any suggestions to share, or any thoughts about why you chose one over the other, I’d love to hear it!

Hello Roger,

Not sure if this helps but I did actually make a few notes for myself when I finished restructuring!

• Use models (modular content) as sections on a page rather than for generating individual pages

• Models: Think multiple / group use. Stand alone elements that would typically appear more than once on a page such as a list of products

• Blocks: Think singular use. Typically appearing once on a page such a testimonial block

• Use ’switch’, ‘case’, and ‘_modelApiKey’ when querying blocks

Hope you find that helpful in some way - I certainly did!

Thanks again,

Richard

1 Like