Interpolating strings in a graphQL query

Exploring the world of Gatsby and its graphQL query system for asset retrieval is a fascinating journey. I have successfully implemented a component called Image that fetches and displays images. However, I am facing a challenge in customizing the name of the image within this component.

Let me share with you the current working component:

const Image = () => (
  <StaticQuery
    query={graphql`
      query {
        // Fetching the image gatsby-astronaut.png
        placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
  />
);

Now, let me show you my attempt to make the image name customizable:

const Image = ({ imgName }: { imgName: string }) => (
  <StaticQuery
    query={graphql`
      query {
        // Fetching the image based on dynamically passed imgName
        placeholderImage: file(relativePath: { eq: "${imgName}.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
  />
);

However, this implementation results in the following error message related to the query:

Expected 1 argument, but received 2.ts(2554)

I would greatly appreciate any guidance or insights on how to achieve a customizable image name within the Gatsby Image component.

Answer №1

Here's a simple method I came across:

const Picture = props => {
  const data = useStaticQuery(graphql`
    query {
      primaryPic: file(relativePath: { eq: "firstImg.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }

      secondaryPic: file(
        relativePath: { eq: "secondImg.png" }
      ) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  switch (props.name) {
    case "firstImg":
      return <Img fluid={data.primaryPic.childImageSharp.fluid} />
    case "secondImg":
      return <Img fluid={data.secondaryPic.childImageSharp.fluid} />
    default:
      return <Img />
  }
}

and implement it like this:

<Picture name="primaryPic" />

You can also enhance it to be typo-proof by creating an object with all the images you plan to showcase, for instance:

const Pictures = { primaryPic: 'primaryPic', secondaryPic: 'secondaryPic' }

and then utilize it in this way:

<Picture name={Pictures.primaryPic} />

and

...
switch (props.name) {
case Pictures.primaryPic:
...

Answer №2

Refer to the documentation for static query

StaticQuery has similar capabilities to page query, including handling fragments. The key distinctions are:

  • Page queries can accept variables (via pageContext) but are limited to usage in page components
  • StaticQuery does not support variables (hence the term “static”), yet it can be utilized in any component, even on pages

Consider querying for the image's GatsbyImageSharpFluid within your page query and then passing it as the fluid prop directly to Gatsby image.

Answer №3

Thanks to ksav's answer, I was able to successfully implement this solution by utilizing pageQuery and accessing the desired images for a specific page through props.

Here's an example:

export const pageQuery = graphql`
  coverImage: file(relativePath: { eq: "coverImage.png" }) {
    childImageSharp {
      fluid(maxWidth: 600) {
        ...GatsbyImageSharpFluid_tracedSVG
      }
    }
  }
}`

By adding this to your page component, you will have access to the prop coverImage containing the image "coverImage.png". Hope this explanation is helpful!

Answer №4

In my opinion, one area for improvement in Gatsby is its handling of imported images. While @ramzesenok's answer is helpful when using the Gatsby framework with graphql, there is also the option to revert back to traditional React by following a similar process:

import React from 'react';
import gatsbyAstronaut from './gatsby-astronaut.png'; 

and then utilize it like this.

<img src={gatsbyAstronaut} alt="Gatsby Astronaut" />

Although this method may add some weight to your project, the import step is necessary for webpack to bundle the image correctly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The process of extracting data from a form and storing it as global variables

Consider the following example: This is our HTML form <form action="test1" method="GET" name="frm"> First name: <input type="text" name="fname"><br> Last name: <input type="text" name="lname"><br> <i ...

Altering the hue of a picture

Looking to alter the color of an image on a webpage, specifically a carport. It's crucial that the texture and shadows remain consistent. Swapping out images with different colors would require an excessive amount of images, so I'm seeking advice ...

Using AngularJS location.path for unique custom URLs

Control Code: $scope.$on('$locationChangeStart', function () { var path = $location.path(); var adminPath = '/admin/' ; if(path.match(adminPath)) { $scope.adminContainer= function() { return true; }; }); HTML <div clas ...

A fatal error has occurred in Node as it is unable to set headers after

Just getting started with nodeJs and I'm attempting to read a file from the system. It seems like I can view the file content in the console, but for some reason it's not displaying in the browser. Any ideas what I might be overlooking? var myD ...

Fluctuating updated site (ajax)

What method do you recommend for maintaining the data in a table on a page current? Currently, I am using a timer that connects to the server via ajax every 2 seconds to check for updates. Is there a way to trigger an event or function only when the cont ...

Encountering a problem with TypeScript while employing Promise.allSettled

My current code snippet: const neuroResponses = await Promise.allSettled(neuroRequests); const ret = neuroResponses.filter(response => response?.value?.data?.result[0]?.generated_text?.length > 0).map(({ value }) => value.data.result[0]?.genera ...

Displaying multi-dimensional arrays through the console in JavaScript and showcasing their elements

My array is supposed to have 140 indexes in a single format like this: array:[0-140] //however, it currently appears as: array: [ 0: [0-99], 1: [100-140] ] I've confirmed multiple times that it is just one array of objects. Why is it s ...

Enhance the list visualization in Next.js by efficiently transferring data from child components

In my Next.js Page component, I have a setup similar to the following: export default function Index({ containers }) { const [containerListState, setContainerListState] = useState(containers); const updateContainerList = (container) => { contai ...

What exactly is the purpose of calling upon 'express' - a reference to a function or an object?

It is my belief that by utilizing var express = require('express');, the variable express receives a function reference of createApplication(). So, when we invoke express(), it will yield an app object. However, my question is, if var express is ...

The useState variable's set method fails to properly update the state variable

I am currently developing an application with a chat feature. Whenever a new chat comes in from a user, the store updates an array containing all the chats. This array is then passed down to a child component as a prop. The child component runs a useEffect ...

XDomainRequest for cross-domain ajax is throwing an error that is difficult to understand - an empty error message

Here is my AJAX call to a page on a different domain: if ($.browser.msie && window.XDomainRequest) { // Use Microsoft XDR var xdr = new XDomainRequest(); xdr.open("post", "https://different-domain.aspx"); ...

A step-by-step guide to incorporating VeeValidate with vue-i18n

When a click event is triggered, I am able to change the language in vue-i18n. However, I am facing an issue with changing the vee-validate dictionary to match the same language. Main.js import VeeValidate from 'vee-validate' import validations ...

callbacks in amazon-cognito-identity-js

When working with amazon-cognito-identity-js, I encountered an issue with the callback function. This is what it currently looks like: cognitoUser?.getUserAttributes((err, results) => { if (err) { console.log(err.message || JSON.stringify(err)); ...

Occasional TypeError when receiving JSONP response using jQuery .ajax()

Occasionally, I encounter an error message stating Uncaught TypeError: undefined is not a function when processing the JSONP response from my jQuery .ajax() call. The JSON is returned successfully, but sometimes this error occurs during the reading process ...

A guide to examining pixels in Three.js

I have a query about comparing two textures at a pixel level in three.js. I am unsure of how to achieve this as the documentation for Three.js does not provide clear answers, with some classes remaining undocumented. In summary, I am looking to determine ...

Packages required for plugins on Npm

I am fairly new to NPM dependencies and I'm currently transitioning from the Ruby world. Working on a Chrome extension utilizing React, in my content.js script, I have the following code at the top: var React = require("react"); var $ = require("jqu ...

How to retrieve data obtained from parsing readline and fs in node.js beyond the scope of the callback function

This specific question diverges from the one mentioned with an existing answer. It pertains to a snippet of code taken from node.js documentation involving the use of fs and readfile, with a focus on detecting an end-of-file flag, which appears to be the r ...

Angular service is able to return an Observable after using the .then method

I am currently facing an issue with retrieving the authentication status in a service method. Everything seems to be working fine except for the return statement. I am struggling with the usage of .then inside .map and I am unable to figure out how to retu ...

Getting the ng-model value from a Directive's template and passing it to a different HTML file

When working with my name directive, I am unable to retrieve the value of ng-model from the template-url. team-two.html <form name="userForm" novalidate> <div name-directive></div> </form> <pre>{{userForm.firstname}}< ...

Incorporate VLC player into a webpage without any visible control options

Is there a way to embed a flash video in a webpage without showing any controls? I managed to embed a flash video using VLC with the following code: <embed src="img/Wildlife.wmv" height="480" width="640"> However, I want the video to play without ...