I have a component that works as a collapsible ui element where an image is loaded when opened. These collapsible elements are part of a list, and I need the image to be a variable since it's different on each list item.
I understand that I need to use Dynamic Images in Gatsby, since Static Images can't use props, and I need to resolve the image name from a prop.
Trying to use Dynamic Image, I'm getting "undefined" when trying to resolve the image from a prop. According to this post, you can't use GraphQL inside a component that is not in the /pages directory. Instead they are suggesting the use of Fragment, and that's where I'm stuck trying to figure out how to use it in my specific case.
Here's what I'm trying to do in src/components/Collapsible.js:
import React, { useState } from "react";
import { GatsbyImage } from "gatsby-plugin-image";
function Collapsible({ hit, children }) {
const [isOpen, setIsOpen] = useState(false);
const image = "../images/reference/render/" + hit.name;
return !isOpen ? (
<tr className="row" onClick={() => setIsOpen(!isOpen)}>
{children}
</tr>
) : (
<tr>
<td colSpan="4">
<div className="material-card">
<div>
<h1 onClick={() => setIsOpen(!isOpen)}>{hit.name}</h1>
<p>{hit.category}</p>
<div className="thumbnail">
<GatsbyImage image={image}/>
</div>
</div>
</div>
</td>
</tr>
);
}
export default Collapsible;
Somehow I'm supposed to be able to create a Fragment using my GraphQl query, which looks like this:
query Image {
file(relativePath: {eq: "reference/render/image1.png"}) {
id
childImageSharp {
gatsbyImageData(
width: 300
placeholder: NONE
quality: 75
layout: CONSTRAINED
)
}
}
}
Any ideas?
This line:
Is returning a path, while when using
GatsbyImage
you need to provide a full object withgatsbyImageData
as animage
property. The approach will work when rendering "standard"<img>
in thesrc
attribute but not withGatsbyImage
since yourimage
variable doesn't contain the data thatGatsbyImage
needs.Moreover, your GraphQL query fragment I'm not sure where it's used, but not in any snippet you've shared. The problem here is that you are trying to combine dynamic images with static queries, where you can't use dynamic filters:
hit.name
will be something dynamic and you cannot combine it with static queries hence they don't accept dynamic parameters.That said, I think a valid workaround will be using a useStaticQuery hook to get
allFile
node withgatsbyImageData
in it and filter the array usinghit.name
or with therelativePath
.allFile
will hold all your images so that you only need to filter it using JavaScript.Note: Test the query in the
localhost:8000/___graphql
before to ensure that the query is returning the correct data. Tweak thenode => node.relativePath === "../images/reference/render/" + hit.name
to match your specific filter, this is an example.The static query will hold your data inside
data.allFile
, there, usinghit.name
you can filter the array of images and get the needed one. This image, since it's queried and holdinggatsbyImageData
, will be a valid image to use inGatsbyImage