0

I'm an iOS developer and I've been struggling for what seems like the longest time making my portfolio site from scratch. I've tried a bunch of different technologies and have finally settled on using Gatsby to create it.

So far things have been fairly straightforward but I can not figure out for the life of me how to get a component that looks like the picture below. I've gotten most of the layout design working, but I can't seem to use graphql to query the images I need in the component.

Desired Layout

enter image description here

I've found plenty of Gatsby example templates such as this one and this one that are similar. However the main difference is that each of these only have one image and they seem to be using Gatsby 2.0 instead of 3.0.

I can get one image using "useStaticQuery", however I need access to different images for each component. From my understanding this is not possible to do within a component, only on a page. I also can not pass the image path as a variable to StaticImage either.

export default function App(props) {
  const query = useStaticQuery(graphql`
    query AppSectionImages {
      icon: file(relativePath: { eq: "EzMaxRequest/AppIcon_180.png" }) {
        childImageSharp {
          gatsbyImageData(
            width: 200
            placeholder: BLURRED
            formats: [AUTO, WEBP, AVIF]
          )
        }
      }
    }
  `);
  const image = getImage(query.icon);
  const app = props.app;

  return (
    <div>
      <h1>{app.title}</h1>
      <GatsbyImage image={image} />
    </div>
  );

Result

enter image description here

Can anyone please explain to me how I can get the desired layout in a component?

Edit

Here is some relevant code of what I am doing.

This is my index.js home page.

export default function IndexPage({ data }) {
  const projects = data.apps.edges;
  return (
    <Layout>
      <SEO title="Home" />
      <HeroSection />
      <DescriptionSection />
      <div>
        {projects.map(({ node: project }) => (
          <AppSection app={project} />
        ))}
      </div>
      <FooterSection />
    </Layout>
  );
}

//export page query
export const query = graphql`
  query Apps {
    apps: allAppsJson(sort: { order: ASC, fields: order }) {
      edges {
        node {
          appLink
          title
          tagline
          moreLink
          order
          icon
        }
      }
    }
  }
`;

Here is the component.

export default function App(props) {
  const query = useStaticQuery(graphql`
    query AppSectionImages {
      icon: file(relativePath: { eq: "EzMaxRequest/AppIcon_180.png" }) {
        childImageSharp {
          gatsbyImageData(
            width: 200
            placeholder: BLURRED
            formats: [AUTO, WEBP, AVIF]
          )
        }
      }
    }
  `);
  const image = getImage(query.icon);
  const app = props.app;

  return (
    <div>
      <h1>{app.title}</h1>
      <GatsbyImage image={image} alt={app.title} />
    </div>
  );
}
Richard Witherspoon
  • 4,082
  • 3
  • 17
  • 33

1 Answers1

1

You have a few options:

  1. Query for all of your image data in your page query and prop-drill the data to the component that uses it to display the image.
  2. Using Gatsby v3+, hardcode the image references for each component using the new StaticImage component.
  3. If you have a single component used multiple times with different content/images, but a static parent component with your content, you can leverage option #2 above but pass the image component down as a prop or children.
coreyward
  • 77,547
  • 20
  • 137
  • 166
  • The first solution doesn't seem like it would be a good solution. 5 project x 4 images each is a lot to query. – Richard Witherspoon Apr 28 '21 at 19:06
  • As for the other solutions you suggested I’m not sure they would work either. I have my index.js page which holds my desired layout. I'm mapping over each project and using a Container component to display each project. I'm currently passing each project as a prop. I will update the question to show some code. – Richard Witherspoon Apr 28 '21 at 19:08
  • This is the way that Gatsby Image works with static images. If you'd prefer a less rigid/explicit/coupled approach, check out [Sanity.io](https://www.sanity.io/) and my [gatsby-plugin-sanity-image plugin](https://github.com/coreyward/gatsby-plugin-sanity-image). You can then simply expand the GraphQL fragment on any field with an image, use fragments to define queries for your components, and simply assemble them together in your page or template query. – coreyward Apr 28 '21 at 21:11
  • 1
    To be clear, there is no way to run a query in a component each time it is used. Gatsby extracts GraphQL queries via static-analysis and uses a hash of the hardcoded string to associate the results of the query with the component running it (that's what the `graphql` tagged template literal function does). It's limiting, but this constraint is what allows Gatsby to handle your data pipeline and build static entry-points to your app for each page while doing lighter weight client-side navigation once a page is loaded. – coreyward Apr 28 '21 at 21:14
  • If this is the case perhaps I’m using the wrong technology? I feel like this should be pretty straightforward. I just need images and text on this website. – Richard Witherspoon Apr 28 '21 at 21:39
  • 1
    Maybe. You can certainly go simpler if you don't care about making images responsive, offering compressed versions in optimal formats for compatible browsers, or deferring loading to improve page-load times. Gatsby is not a minimalist tool aiming to be a simple way to get a small personal site up—if you want something that is, you may be happier with Eleventy or Hugo. – coreyward Apr 28 '21 at 22:03