Multiple Images in Gatsby with a Single Component


May 2020

Image generation is one of the key performance boosters provided by Gatsby.js.

Of course a little work is required ahead of time, as explained in the official docs. While I believe that is totally worthwhile, it will never hurt to find ways to simplify our life as developers.

Specifically, I was not thrilled with the idea of generating a separate component for every optimized image that I wish to manually import:

import React from "react";
import { useStaticQuery, graphql } from "gatsby";
import Img from "gatsby-image";
const Image = () => {
const data = useStaticQuery(graphql`
query {
image: file(relativePath: { eq: "home.png" }) {
childImageSharp {
fixed(width: 40, height: 40) {
...GatsbyImageSharpFixed
}
}
}
}
`);
return <Img fixed={data.image.childImageSharp.fixed} />;
};
export default Image;

I found a few alternative solutions on the web, but none of them looked clean and satisfying to me.

So I started experimenting, and I came up with something as simple as a single GraphQL query followed by a switch statement:

import React from "react";
import { useStaticQuery, graphql } from "gatsby";
import Img from "gatsby-image";
const Image = ({ name }) => {
const data = useStaticQuery(graphql`
query {
home: file(relativePath: { eq: "home.png" }) {
childImageSharp {
fixed(width: 40, height: 40) {
...GatsbyImageSharpFixed
}
}
}
photo: file(relativePath: { eq: "stefano.jpg" }) {
childImageSharp {
fixed(width: 270, height: 270, quality: 100) {
...GatsbyImageSharpFixed
}
}
}
smallerphoto: file(relativePath: { eq: "stefano.jpg" }) {
childImageSharp {
fixed(width: 120, height: 120, quality: 100) {
...GatsbyImageSharpFixed
}
}
}
}
`);
switch (name) {
case "home":
return <Img fixed={data.home.childImageSharp.fixed} />;
case "photo":
return <Img fixed={data.photo.childImageSharp.fixed} />;
case "smallerphoto":
return <Img fixed={data.smallerphoto.childImageSharp.fixed} />;
default:
console.log("No valid image name provided");
return null;
}
};
export default Image;

Now we can query any number of images within a single Image component, and get it to return the desired image by including a name prop. Here's how we go about it in our JSX:

import React from "react";
import Image from "../components/image";
const Page = () => (
<>
<Image name="home" />
<Image name="photo" />
<Image name="smallerphoto" />
</>
);
export default Page;

I hope this helps!

© 2024 Stefano Picker