#Fetching Images from Strapi.

1 messages · Page 1 of 1 (latest)

stark lily
#

Hi. I am having trouble fetching a group of images from a Strapi CMS. Here is my code; which displays nothing and VSCode returns a Type '{ src: string; alt: any; }' is not assignable to type 'IntrinsicAttributes & Props' error.

<div class="company__images">
  {company.work?.map(image =>
    <Picture src={`${STRAPI_URL}${image.formats.large.url}`} alt={image.alternativeText} />
  )}
</div>
stark lily
#

I did get the error on VSCode to disappear by doing this:

const workImages: any[] = company.work;

<div class="company__images">
  {workImages?.map((work) => (
    <Image 
      src={`${STRAPI_URL}${work.url}`} 
      alt={work.alternativeText} 
      width="500"
      height="700"
    />
  ))}
</div>
#

However I still don't see the images on the page.

umbral patrol
stark lily
stark lily
#

The problem is that the company.work.map() resursive function isn't working. The idea is to grab the images from the Strapi REST API.

runic bone
#

Some troubleshooting ideas:
Check your network tab. Tell us if you see any data being returned, if it's empty or if it's an error.
If there's data, make sure the json structure matches what you're using to display it.
If it's empty or lacking fields, check out https://docs.strapi.io/cms/api/rest/populate-select
I haven't used Strapi in a while so I might not be able to help with specifics
If there's an error tell us what it says. Is other content being fetched properly?

Use Strapi's REST API to populate or select certain fields.

umbral patrol
stark lily
umbral patrol
#

If you log the workImages array on in the frontmatter, does it show the images? Or is the array empty?

stark lily
#

This is what it returns when I use localhost:1337/api/companies?populate=*

#

And here's the code that I'm having trouble with.

---
import Layout from "../../layouts/Layout.astro";
import "../../styles/global.css";
import fetchApi from "../../lib/strapi";
import type Company from "../../interfaces/company";
import { Image } from "astro:assets";

export async function getStaticPaths() {
  const companies = await fetchApi<Company[]>({
    endpoint: 'companies',
    wrappedByKey: 'data',
  });

  return companies.map((company) => ({
    params: { slug: company.slug },
    props: company,
  }));
}

type Props = Company;

const company = Astro.props;

const STRAPI_URL = "http://localhost:1337";

const workImages: any[] = company.work;
---

<Layout title={`${company.name} | Graphic Designer`}>
  <main id="company">
    <div class="wrapper">
      <h1 class="title company__name">{company.name}</h1>
      <p class="description company__description">{company.description}</p>

      <div class="company__images">
        {company.work?.map((work) => (
          <Image 
            src={`${STRAPI_URL}${work.url}`} 
            alt={work.alternativeText} 
            width="500"
            height="700"
          />
        ))}
      </div>
    </div>
  </main>
</Layout>

<style>
</style>
#

For comparison: This is another page that uses similar code that does work.

---
import Layout from "../layouts/Layout.astro";
import { Image } from "astro:assets";
import "../styles/global.css";
import fetchApi from "../lib/strapi";
import type Company from "../interfaces/company";

const STRAPI_URL = 'http://localhost:1337';

const companies = await fetchApi<Company[]>({
  endpoint: "companies?populate=*",
  wrappedByKey: 'data',
});
---

<Layout title="My Work | Graphic Designer">
  <main id="my-work-index">
    <div class="wrapper">
      <h1 class="title">My Work</h1>
      <p class="description">
        My experience is in creating promotional materials for [redacted to prevent doxing] area companies and organizations. 
        Here is an example of my best work.
      </p>

      <div class="companies">
        {companies.map((company) => (
          <div class="company">
            <a class="company__thumbnail" href={`/work/${company.slug}`}>
              <Image 
                src={`${STRAPI_URL}${company.thumbnail.url}`}
                alt={`Thumbnail of work for ${company.name}`}
                width="245"
                height="147"
              />
            </a>
            <a href={`/work/${company.slug}`}>
              <span class="company__name">{company.name}</span>
            </a>
          </div>
        ))}
      </div>
    </div>
  </main>
</Layout>
umbral patrol
#
---
import Layout from "../../layouts/Layout.astro";
import "../../styles/global.css";
import fetchApi from "../../lib/strapi";
import type Company from "../../interfaces/company";
import { Image } from "astro:assets";

export async function getStaticPaths() {
  const companies = await fetchApi<Company[]>({
    endpoint: 'companies',
    wrappedByKey: 'data',
  });

  return companies.map((company) => ({
    params: { slug: company.slug },
    props: company,
  }));
}

type Props = Company;

const company = Astro.props;

const STRAPI_URL = "http://localhost:1337";

const workImages: any[] = company.work;
console.log(workImages);
---

<Layout title={`${company.name} | Graphic Designer`}>
  <main id="company">
    <div class="wrapper">
      <h1 class="title company__name">{company.name}</h1>
      <p class="description company__description">{company.description}</p>

      <div class="company__images">
        {company.work?.map((work) => (
          <Image 
            src={`${STRAPI_URL}${work.url}`} 
            alt={work.alternativeText} 
            width="500"
            height="700"
          />
        ))}
      </div>
    </div>
  </main>
</Layout>

<style>
</style>

If you try this code (with an added console.log), what does it show in your server console (not the browser)?

stark lily
# umbral patrol ```tsx --- import Layout from "../../layouts/Layout.astro"; import "../../styles...

I got this on the server console...

20:05:05 watching for file changes...
20:05:07 [200] / 13ms
20:05:08 [200] /_image 166ms
20:05:09 [200] /work 50ms
undefined
20:05:10 [200] /work/seeds-of-hope 3ms
undefined
20:05:22 [200] /work/seeds-of-hope 5ms
20:05:24 [WARN] [router] A `getStaticPaths()` route pattern was matched, but no matching static path was found for requested path `/work/installHook.js.map`.

Possible dynamic routes being matched: src/pages/work/[slug].astro.
20:05:24 [404] /work/installHook.js.map 2ms
#

For comparison, this is what I'm getting on another page that does have working images and text being fetched from Strapi.

20:06:58 watching for file changes...
20:07:00 [200] /work 24ms
20:07:00 [404] /installHook.js.map 1ms
20:07:01 [200] /work 15ms
20:07:01 [404] /installHook.js.map 1ms
umbral patrol
#

It seems that company.work is undefined, according to your console. Could you double-check if you're fetching the data correctly?

#

In fact, removing the ? in company.work.map( should show this by throwing an error

stark lily
#

And indeed it does throw an [ERROR] Cannot read properties of undefined (reading 'map') error.

umbral patrol
#

Its probably an issue with your call to Strapi then. I can't really help without access to the project and have not a lot of experience with Strapi unfortunately

runic bone
#

I had a similar issue at some point with something like months ago and there was an easy fix, can't tell you now bc I don't remember and I'm heading to bed rn but I'll take a look tomorrow

#

Long story short, something is populating the slug with "installHook.js.map" string for some reason and we need to make sure the actual slug is inserted

stark lily
#

Ok. I was gonna try a console log to see if I’m even getting the array of images

stark lily
#

I can confirm that

const workImages: any[] = company.work;
console.log(workImages);
#

returns: [200] /work/seeds-of-hope

#

Solved it: I was missing the ?populate=* in the endpoint.

#

Thanks for the help @runic bone

#

"The best solution to a problem is usually the easiest one."

lyric owlBOT
#
If your issue is resolved, please help by doing the following two steps:
  1. From the ellipses (3-dot menu) in the top-right corner of the post (not the first message), edit the tags to include the Solved tag.
  2. From the same ellipses, select Close Post.
    Your post will still be available to search and can be re-opened simply by replying in it. Closing a post moves it down with older posts, so we can more easily focus on issues that still need to be resolved.
    Thank you for your help!
runic bone
#

Ah, so it was populate after all! Remember to be careful with it @stark lily, it might slow down the site heavily, as you're fetching everything that's possible at once from that particular endpoint. Experiment with different parameters and levels and see what works best, you can also write very specific queries with the endpoint URL alone