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!