{
menu: allMenuJson {
nodes {
id
title
description
link
image {
src {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
menu.json contain the following
[
{
"image": {
"src": "contact.png"
},
},
{
"image": {
"src": "service.png"
},
}
]
images are located at
src/images/menu/contact.png
src/images/menu/service.png
How do i query to display the image using gatsby-image component?
<Img fluid={menu.image.src..childImageSharp.fluid} /> is not working
<Img fluid={menu.image.src..childImageSharp.fluid} /> is not working
Do you have those two dots between src and childImageSharp in your code? Because that will break it.
No there are no two dots. It is a mistake,
if i make the following changes in my menu.json it works.
[
{
"image": {
"src": "../images/menu/contact.png"
},
},
{
"image": {
"src": "./images/menu/service.png"
},
}
]
But i just want to keep only the image name in the json file. Is that possible?
@maheshkumar2150 short answer, the first approach will only work with gatsby-image
and it's accompanying plugins gatsby-transformer-sharp
and gatsby-plugin-sharp
and also gatsby-source-filesystem
if the images are in the same folder as the json file. Namely something like:
|root
| content
-menu.json
-contact.png
- service.png
Otherwise you have to include the relative path to the images as technically gatsby would not know where to look.
Let me see if i can create a small repo that could offer a workaround for your issue.
Do you mind waiting a bit?
Yes. I can wait.
Your solution is good.
I have data folder. In that folder, i have few json files.
The problem is i have to include all the images in that data folder. That is the only drawback.
data/menu.json
data/other.json
if gatsby can find the images in data/menu/ and data/other/ it will easier to manage images properly
@maheshkumar2150 i have a possible solution for your issue.
Here are the steps i took to triage your issue.
gatsby-image
, and it's accompanying plugins gatsby-transformer-sharp
and gatsby-plugin-sharp
so that we can take advantage of the full benefits of the plugins.gatsby-transformer-json
to the site.gatsby-config.js
to the following, leaving in only the relevant portion of the content :module.exports = {
.....
plugins: [
....
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./src/data/`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-transformer-json`,
....
}
],
}
The folder /src/data
will contain 2 json files, one called menu.json
and another called other.json
.
The /src/images
folder is the default one that is used in gatsby.
menu.json
.[
{
"title":"Contact",
"description":"This is the contact page",
"link":"/contact/",
"image":{
"src":"contact.png"
}
},
{
"title":"Services",
"description":"This is the services page",
"link":"/services/",
"image":{
"src":"service.jpg"
}
}
]
other.json
:[
{
"content":"Doggo ipsum long doggo smol borking doggo with a long snoot for pats long woofer very taste wow I am bekom fat doggorino, pats h*ck borking doggo wow such tempt floofs, pats wow very biscit most angery pupper I have ever seen long water shoob. Heckin good boys fluffer boofers adorable doggo woofer, puggorino pats. Shibe big ol bork blop, what a nice floof pupperino. Heckin good boys long bois bork waggy wags long bois, long woofer length boy much ruin diet.",
"image":{
"src":"randomimage_1.jpg"
}
},{
"content":"Aqua doggo big ol borkf floofs long water shoob blep heckin good boys and girls, porgo very good spot you are doing me the shock adorable doggo. Shibe aqua doggo vvv extremely cuuuuuute shoob doge, such treat borkf yapper. Smol heckin good boys and girls puggorino tungg pats you are doing me a frighten much ruin diet, borkf fluffer floofs very taste wow.",
"image":{
"src":"randomimage_2.jpg"
}
}
]
The content added is a extrapolation based on your description.
Now 2 approaches to your issue will be documented. The first is more simple and straightforward the other is a bit more advanced, as it will use some gatsby apis.
Going to start with the simple approach.
/src/pages/index.js
to the following:import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import Img from "gatsby-image"
import SEO from "../components/seo"
const IndexPage = ({ data }) => {
const { menu, allImageContent, other } = data
return (
<Layout>
<SEO title="Home" />
<h1>Simple example</h1>
<div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ margin: "1.3rem" }}>
<h3>menu</h3>
<div>
{menu.edges.map(item => {
// fetches the image based on the value that that is set on the appropriate json element
const imageForMenu = allImageContent.edges.find(
element =>
element.node.fluid.originalName === item.node.image.src
)
return (
<div key={item.node.id}>
<h4>{item.node.title}</h4>
<h5>{item.node.description}</h5>
<Img fluid={imageForMenu.node.fluid} />
<Link to={item.node.link}>{item.node.title}</Link>
</div>
)
})}
</div>
</div>
<div>
<div style={{ margin: "1.3rem" }}>
<h3>content</h3>
{other.edges.map(item => {
// fetches the image based on the value that that is set on the appropriate json element
const imageforOther = allImageContent.edges.find(
x => x.node.fluid.originalName === item.node.image.src
)
return (
<div key={item.node.id}>
<Img fluid={imageforOther.node.fluid}/>
<h4 style={{margin:'0.8rem'}}>
{item.node.content}
</h4>
</div>
)
})}
</div>
</div>
</div>
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
}
/**
* query that will fetch all of the json file content and also all of the images
*/
export const pagequery = graphql`
query {
menu: allMenuJson {
edges {
node {
id
title
description
link
image {
src
}
}
}
}
other: allOtherJson {
edges {
node {
id
content
image {
src
}
}
}
}
allImageContent: allImageSharp {
edges {
node {
fluid(maxWidth: 300) {
originalName
...GatsbyImageSharpFluid
}
}
}
}
}
`
export default IndexPage
This a is pretty straightforward page that contains a page query, that will fetch all of the contents of the json files and also the images, goes over each element for each file, grabs the appropriate image based on what is defined on the json and displays it.
gatsby develop
and opened up http://localhost:8000
and i'm presented with the following:On the left is the contents of the menu.json
and the corresponding images and on the right the contents of the other.json
and the corresponding images.
Moving onto the more advance approach.
Gatsby among a lot of diferent t features available, lets you manipulate the nodes that are created during the build process, With this you can grab a node from one source and extend it to incorporate another. And that's what is going to be described below:
gatsby-node.js
with the following code:/**
* gatsby internal api hook that will be triggered after each node is created
* @param {Object} node is the internal gatsby node "object" that will be available in the data layer i.e graphQL layer
* @param {Object} actions contains the set of options available.
*/
exports.onCreateNode = ({ node, actions }) => {
// destructures the needed action
const { createNodeField } = actions
//
// checks the gatsby node type
// in this case we are looking for the json content that exists and transformed by the gatsby-transformer-json plugin
if (node.internal.type === "MenuJson") {
// extends the existing gatsby node with a new field, later accessible via the fields graphql node.
createNodeField({
node, // the current node
name: `menuImage`, // defines a name for the new element being added.
value: `../images/${node.image.src}`, //Injects the value, this will be relative to the path of the json, it will look into /src/images
})
}
if (node.internal.type === "OtherJson") {
// extends the existing gatsby node with a new field, later accessible via the fields graphql node.
createNodeField({
node, // the current node
name: `otherImage`, // defines a name for the new element being added.
value: `../images/${node.image.src}`, //Injects the value, this will be relative to the path of the json, it will look into /src/images
})
}
}
What is happening in this snippet of code, is the following, gatsby will check the node type is the one associated to the one created by gatsby-transformer-json
and will extend it and inject a new field to that node that will contain a reference to the image file to be used. For more information about this see here also here and here.
/src/pages/page-2.js
to the following content:import React from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import SEO from "../components/seo"
const SecondPage = ({ data }) => {
const { menu, other } = data
return (
<Layout>
<SEO title="Page two" />
<h1>Page with nodes extended and combined</h1>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ margin: "1.3rem" }}>
<h3>menu</h3>
<div>
{menu.edges.map(item => {
return (
<div key={item.node.id}>
<h4>{item.node.title}</h4>
<h5>{item.node.description}</h5>
<Img
fluid={item.node.fields.menuImage.childImageSharp.fluid}
/>
<Link to={item.node.link}>{item.node.title}</Link>
</div>
)
})}
</div>
</div>
<div style={{ margin: "1.3rem" }}>
<h3>content</h3>
{
other.edges.map(item=>{
return (
<div key={item.node.id}>
<Img fluid={item.node.fields.otherImage.childImageSharp.fluid}/>
<h4 style={{margin:'0.8rem'}}>
{item.node.content}
</h4>
</div>
)
})
}
</div>
</div>
<Link to="/">Go back to the homepage</Link>
</Layout>
)
}
// page query with the updated fields that were created in gatsby-node.js making the query more streamlined.
export const query = graphql`
query {
menu: allMenuJson {
edges {
node {
id
title
description
link
image {
src
}
fields {
menuImage {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
other: allOtherJson {
edges {
node {
id
content
fields {
otherImage {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
}
`
export default SecondPage
gatsby clean && gatsby develop
to purge any cached data and restart the development server once again. Opened up a new browser window to http://localhost:8000/page-2/
and i'm presented with the following:Once again the content is similar as it was on the index page. But now you avoid filtering the image data associated to each element through javascript and have it already directly available. With this it will make the queries more streamlined.
Adjusting to your case will probably won't be to difficult to implement. I've setup a repo with the code used for this issue here so that you can look it at your own pace.
Depending on your knowledge of gatsby i would start with the first approach, fiddle with it and when you're more knowledgeable of the apis and internals of gatsby i would move into the second one and go from there.
Feel free to provide feedback so that we can close this issue or continue to work on it until we find a suitable solution.
Man, you are an extraordinary person.
Thank you so much!
@maheshkumar2150 no need to thank, glad that i was able to help out and offer some insights on your issue.
@maheshkumar2150 can we close this issue?
I'm going to close this issue, feel free to open it back up or open a new issue if you run into something new @maheshkumar2150 馃檪
Thanks for the help on it @jonniebigodes!!
@gillkyle i left it open, so that i could "hear" some feedback from @maheshkumar2150 to confirm that he had it up and running and was able to solve is issue. No need to thank, glad that i was able to supply a clear and helpful resolution for it
@jonniebigodes thanks for your amazing solution, the "advance approach" works really well.
One appendix, if you happen to have a list of images, this works for me:
in data.json
:
{
// other properties
"images": [
{
"src": "test.png"
},
{
"src": "test1.png"
}
]
}
in gatsy-node.js
if (node.internal.type === "DataJson") {
createNodeField({
node,
name: `image`,
value: node.images.map(image => `./../src/images/${image.src}`)
})
}
@jonniebigodes 1 year later, your answer came to my rescue, thank you!
Most helpful comment
@maheshkumar2150 i have a possible solution for your issue.
Here are the steps i took to triage your issue.
gatsby-image
, and it's accompanying pluginsgatsby-transformer-sharp
andgatsby-plugin-sharp
so that we can take advantage of the full benefits of the plugins.gatsby-transformer-json
to the site.gatsby-config.js
to the following, leaving in only the relevant portion of the content :The folder
/src/data
will contain 2 json files, one calledmenu.json
and another calledother.json
.The
/src/images
folder is the default one that is used in gatsby.menu.json
.other.json
:The content added is a extrapolation based on your description.
Now 2 approaches to your issue will be documented. The first is more simple and straightforward the other is a bit more advanced, as it will use some gatsby apis.
Going to start with the simple approach.
/src/pages/index.js
to the following:This a is pretty straightforward page that contains a page query, that will fetch all of the contents of the json files and also the images, goes over each element for each file, grabs the appropriate image based on what is defined on the json and displays it.
gatsby develop
and opened uphttp://localhost:8000
and i'm presented with the following:On the left is the contents of the
menu.json
and the corresponding images and on the right the contents of theother.json
and the corresponding images.Moving onto the more advance approach.
Gatsby among a lot of diferent t features available, lets you manipulate the nodes that are created during the build process, With this you can grab a node from one source and extend it to incorporate another. And that's what is going to be described below:
gatsby-node.js
with the following code:What is happening in this snippet of code, is the following, gatsby will check the node type is the one associated to the one created by
gatsby-transformer-json
and will extend it and inject a new field to that node that will contain a reference to the image file to be used. For more information about this see here also here and here./src/pages/page-2.js
to the following content:gatsby clean && gatsby develop
to purge any cached data and restart the development server once again. Opened up a new browser window tohttp://localhost:8000/page-2/
and i'm presented with the following:Once again the content is similar as it was on the index page. But now you avoid filtering the image data associated to each element through javascript and have it already directly available. With this it will make the queries more streamlined.
Adjusting to your case will probably won't be to difficult to implement. I've setup a repo with the code used for this issue here so that you can look it at your own pace.
Depending on your knowledge of gatsby i would start with the first approach, fiddle with it and when you're more knowledgeable of the apis and internals of gatsby i would move into the second one and go from there.
Feel free to provide feedback so that we can close this issue or continue to work on it until we find a suitable solution.