简体   繁体   中英

Why do my Astro builds fail when featuredImage is null?

I'm using WPGraphQL to query all of my posts from WordPress. And I'm using Astro to display a list of cards for each of those posts on the front-end.

Here is what that my GraphQL query looks like:

/* BASIC FETCH API */

async function fetchAPI(query, { variables } = {}) {
      const headers = { "Content-Type": "application/json" };
      const res = await fetch(API_URL, {
        method: "POST",
        headers,
        body: JSON.stringify({ query, variables }),
      });
    
      const json = await res.json();
      if (json.errors) {
        console.log(json.errors);
        throw new Error("Failed to fetch API");
      }
      return json.data;
    }

/* ALL POSTS QUERY */

export async function getAllPosts() {
  const data = await fetchAPI(`
        {
          posts(first: 10000) {
            edges {
              node {
                id
                title
                content
                excerpt
                slug
                categories(first: 2) {
                  nodes {
                    slug
                    name
                  }
                }
                featuredImage {
                  node {
                    sourceUrl
                  }
                }
              }
            }
          }
        }
    `);
  return data?.posts;
}

And here is how I am rendering those posts on my blog page:

<Section>
    <Container>
      <div class="post--card--wrapper">
        {page.data.map((post) => (
          <PostCard
            src={post.node.featuredImage.node.sourceUrl}
            href={`/posts/${post.node.slug}`}
            title={post.node.title}
            excerpt={`${post.node.excerpt.slice(0, 120)}...`}
          />
        ))}
      </div>
      <div class="pagination--wrapper py-6">
        {page.url.prev ? (
          <a href={page.url.prev || "#"} class="pagination--previous">
            ← Previous
          </a>
        ) : null}
        {page.url.next ? (
          <a href={page.url.next || "#"} class="pagination--next">
            Next →
          </a>
        ) : null}
      </div>
    </Container>
  </Section>

And this is the code for the PostCard.astro component:

---
export interface Props {
  href?: string;
  src?: string;
  alt?: string;
  title?: string;
  categories?: string;
  excerpt?: string;
}

const { href, src, alt, title, categories, excerpt } = Astro.props;
---

<a href={href} class="post--card">
  {src && <img src={src} alt={alt} class="post--thumbnail" />}
  <div class="post--card--bottom">
    <h5 class="post--card--heading">{title}</h5>
    <div class="post--card--excerpt" set:html={excerpt}></div>
  </div>
</a>

The problem is that a few of the posts do not have featured images set. And so, my builds are failing with the following error message:

"TypeError: Cannot read properties of null (reading 'node')"

I basically want to tell GraphQL to grab the featuredImage field for each post if it exists. But if featuredImage does not exist, keep going and get the rest of them.

Conditionally render elements in Astro

The answer to this in Astro is to conditionally render an element. This is a known pattern

all you have to do is add post.node.featuredImage && in front of the element to render conditionally

<div class="post--card--wrapper">
        {page.data.map((post) => (
          {post.node.featuredImage &&
          <PostCard
            ...
          />
         }
        ))}
      </div>
{featuredImage &&
}

reference in Astro docs: https://docs.astro.build/en/tutorial/2-pages/3/#conditionally-render-elements

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