I’m thinking of using Gatsby-Image for my next project and have been playing around with it a little.
I got it to work on my test project, but then I came up with a use case that I would like to use the <Image /> tag from Gatsby much like a regular <img src”image.png”>
tag. How can I make the Gatsby <Image /> component reusable?
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
function renderImage({ file }) {
console.log({ file })
return <Img fluid={file.childImageSharp.fluid} />
}
// Stateless Image component which I guess will
// receive the 'src' value as a property?
//
// It returns a StaticQuery component with a query property
// and render property. The query property has the GraphQL
// query to receive the images and render prop returns a
// renderImage function which in return, returns an Img
// component from Gatsby with set attributes.
const Image = () => (
<StaticQuery
query={graphql`
query {
file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`}
// render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
render={renderImage}
/>
)
export default Image
My optimal use case would be to make a dynamic request to my relativePath which is defined in my Gatsby.config file and then combine the src property in each Gatsby <Image /> and match it with all my images in my assets file and then display it. Is this even possible with <StaticQuery />?
I read in the documentation that StaticQuery can't take variables - only pages. But I don't want my images to be associated with a page - I want to use this component anywhere I want - like a regular img tag.
This is an example: https://codesandbox.io/s/py5n24wk27
As you pointed out, there's no GatsbyImageData because Gatsby's transformers and sharps ( gatsby-transformer-sharp but especially gatsby-plugin-sharp ) doesn't support SVG. As they are not able to interpret SVG assets, they are not able to create the GraphQL nodes.
This may answer your question:
import React from 'react';
import { StaticQuery, graphql } from 'gatsby';
import Img from 'gatsby-image';
// Note: You can change "images" to whatever you'd like.
const Image = props => (
<StaticQuery
query={graphql`
query {
images: allFile {
edges {
node {
relativePath
name
childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`}
render={data => {
const image = data.images.edges.find(n => {
return n.node.relativePath.includes(props.filename);
});
if (!image) {
return null;
}
//const imageSizes = image.node.childImageSharp.sizes; sizes={imageSizes}
return <Img alt={props.alt} fluid={image.node.childImageSharp.fluid} />;
}}
/>
);
export default Image;
Using the image:
import Image from '../components/Image';
<div style={{ maxWidth: `300px` }}>
<Image alt="Gatsby in Space" filename="gatsby-astronaut.png" />
</div>
Because StaticQuery doesn't support string interpolation in its template literal, we can't really pass it any props. Instead we will try and handle check for props in the StaticQuery's Render portion.
I'm not 100% sure if this affects compiling time since we are scanning all images.
If you have many images, bundle size can get quite large as this solution does scan all images.
You can adjust the code to show a placeholder image if no props are passed.
That said, there is another way you could tackle this, but with a bit more work/code.
Unfortunately, from what I can gather, the best solution is to write out individual JavaScript files for images.
In RodrigoLeon's approach, it will cause the bundle size to increase dramatically. Especially if, say, you have more than 50 images. Because anytime you use this and loop through all images you create references to them in the component file. So I would not recommend doing it this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With