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

What is the best way to manage classNames dynamically in React with Material-UI?

I am wondering how to dynamically add and remove classes from an img tag. My goal is to change the image automatically every 2 seconds, similar to Instagram's signup page. I am struggling to achieve this using the material-ui approach. Below is a snip ...

What causes the React Query cache to be cleared upon page reload?

Hi there, I am new to Next.js and React Query. I would really appreciate any help or advice. I apologize for any mistakes in my English language skills. Currently, I am using Next.js v12 and React Query v3, along with the React Query DevTools. On one of ...

Struggling to properly render JSON data

Having trouble accessing specific elements in a script that merges local JSON files using AJAX? The script works fine in Chrome Console, but you can't reach certain elements like 'object.country'. Any suggestions on how to tackle this issue? ...

Issue: Headers cannot be set again once they have been sent during page reload

Whenever I attempt to refresh a specific page, I encounter an Error: Can't set headers after they are sent. Interestingly, when I click on a link to navigate to that page, the error doesn't occur. I have meticulously reviewed the sequence of even ...

Guidelines on integrating Admob into Ionic framework

I tried following the steps outlined in this post: AdMob not loading ads in ionic/angular app After running the app using "ionic build ios && ionic emulate ios," I still see no ads, no black bar, nothing at all. Can someone help me figure out wha ...

Ubuntu is experiencing a DNS problem. While the URL request works perfectly on MacOSX, it is unsuccessful on Ubuntu

A custom nodeJS script has been developed to utilize the require('request').post() method. The script executes successfully on MacOSX (Travis), however encounters issues on Ubuntu (Travis). To troubleshoot, experimentation with NodeJS 'https ...

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 ...

VueJS method for making an HTTP GET request

Attempting to make an http get request using Vue js. I can't seem to find any issues with the logic, although I'm not very experienced with vuejs. Continuously encountering these two errors: [Vue warn]: Error in mounted hook: "TypeError: Cann ...

Function that returns an Observable<Boolean> value is null following a catch block

Why is the login status null instead of false in this method? // In the method below, I am trying to return only true or false. isLoggedIn(): Observable<boolean> { return this .loadToken() .catch(e => { this.logger ...

Modifications to contenteditable elements result in a change to their IDs

Having some trouble with the behavior of a contenteditable div. The code structure is like this: <div contenteditable="true"> <p id="element-id-1">element-id-1</p> <p id="element-id-2">element-id-2</p> </div> E ...

Ensuring precise accuracy in JavaScript; transforming 0.5 into 0.5000

My current challenge involves converting every fraction number to n decimal places in JavaScript/Node.js. However, I've encountered a roadblock as it appears impossible to convert 0.5 to 0.5000. This discrepancy is causing my test cases that anticipat ...

When accessing a method exposed in Angular2 from an external application, the binding changes are lost

In my code, I have a method that is made public and accessible through the window object. This method interacts with a Component and updates a variable in the template. However, even after changing the value of the variable, the *ngIf() directive does not ...

What is the process for dynamically looping through a table and adding form data to the table?

I am in the process of developing an hour tracking website that utilizes a form and a table. Currently, I have implemented the functionality where the form content gets added to the table upon the first submission. However, I need it to allow users to inp ...

jQuery dropdown menu button impacts the entire webpage

I created this jQuery code to modify the drop menu elements, but it ended up affecting the entire page. How can I resolve this issue? $(".dropmenuac").on("click",function(){ $(".dropmenulist").css("opacity",& ...

Determining when a message has been ignored using php

One of the features I am working on for my app is adding announcements, which are essentially personalized messages to users. Once a user receives a message and dismisses it, I want to ensure that specific message does not appear again. Here is the PHP co ...

Troubleshooting Angular 6: Issues with Route Guards not functioning as expected

Striving to enhance frontend security by restricting access to specific IDs. The goal is to redirect anyone trying to access routes other than /login/:id to a page-not-found error message if not already logged in, but encountering some issues. Below are t ...

How can one deactivate a <MenuItem> component in material-ui?

Currently, I am in the process of developing a personalized combo box using React and Material-UI. This unique combo box will exhibit the chosen value within the input, present a drop-down menu with various options (MenuItems), and feature a text box at th ...

What steps are necessary to configure .eslintrc to identify the use of 'require'?

I recently started using ESLint and successfully integrated it with IntelliJ. Initially, ESLint did not recognize node out of the box. After consulting the documentation, I created a configuration file named .eslintrc at the project's root folder, sp ...

Can TypeScript be set up to include undefined as a potential type in optional chains?

Today, I encountered a bug that I believe should have been caught by the type system. Let me illustrate with an example: function getModel(): Model { /* ... */ } function processModelName(name: string) { return name.replace('x', 'y& ...

"Enhanced interactivity: Hover effects and selection states on an image map

Hello there, I need assistance with my code. Here it is: <img id="body_image" usemap="#body_map" src="assets/images/body.jpg" alt=""> <map name="body_map"> <area shape="poly" alt="d" href="#body_chart" name="ad" coords="153, 153, 145, 1 ...