The goal, Combine two StaticQueries hooks from separate files into single ES6 array map(). Start with two queries hooks
Query hooks #1: useTeamImg,js
import { useStaticQuery, graphql } from 'gatsby';
export const useTeanImg = () => {
const { source } = useStaticQuery(
graphql`
query allImgQuery {
source: allFile(filter: { absolutePath: { regex: "/sponsors/" } }) {
edges {
node {
childImageSharp {
fluid(maxWidth: 2000) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
);
return { source };
};
... Query hooks #2: useUrls.js
import { useStaticQuery, graphql } from 'gatsby';
export const useUrls = () => {
const { urls } = useStaticQuery(
graphql`
query {
urls: allLinkJson {
edges {
node {
url
}
}
}
}
`
);
return { urls };
};
FYI: fetching data of urls from data.json for useUrls hooks
[{
"url": "https://item1.com/"
},
{
"url": "https://item2.com/"
},
{
"url": "https://item3.com/"
},
{
"url": "https://item4.com/"
}
]
The source is set up using gatsby-source-filesystem inside _gatsby-config.js_ and translate json following gatsby-transformer-json plugin.
`gatsby-transformer-json`,
{
/* Data */
resolve: `gatsby-source-filesystem`,
options: {
name: `url`,
path: `${__dirname}/src/assets/data`
}
},
And on my first attempt...
import React from 'react';
import { useStaticQuery, graphql } from 'gatsby';
import { useTeamImg } from '../hooks/useTeamImg';
import { useUrls } from '../hooks/useUrls';
const ComponentA = () => {
const { source } = useSponsorsImg();
const { urls } = useUrls();
const value = { source, urls };
console.log(value);
return (
<div>
{value.edges.map(({ node }, i) => (
<Img key={i} fluid={node.childImageSharp.fluid} />
<p key={i}>url: {node.url}</p>)}
))}
</div>
);
};
export default ComponentA;
Instead of success, I am getting an "Cannot read property 'map' of undefined" even though The browser console shows
{source: {鈥, urls: {鈥}
source: {edges: Array(21)}
urls: {edges: Array(4)}
__proto__: Object
On another attempt which is almost similar as first one but without using const value = {source, urls};
<div>
{{ source, urls }.edges.map(({ node }, i) => (
<div>
<Img key={i} fluid={node.childImageSharp.fluid} />
<p>url: {node.url}</p>)}
</div>
))}
</div>
Still no success with same error.
I am trying to find possibilities and I only wonder if its possible? Any suggestion or better alternatives?
Additional: Do I really need to use gatsby-transformer-json to fetch data from source? Could I use simple js instead i.e.
export default [{
"url": "https://item1.com/"
},
{
"url": "https://item2.com/"
},
{
"url": "https://item3.com/"
},
{
"url": "https://item4.com/"
}
]
Thanks in advance.
@aprather51 I've picked up on your issue and i believe i have a solution for you.
Here are the steps i took to get it working, going to to breakdown into smaller steps:
src/images/sponsors/.Urls.json in src/assets/data to match your setup, with a slight difference as you can see below:[
{
"name":"wallpaper-10053",
"url":"wwww.one.com"
},
{
"name":"wallpaper-1386",
"url":"wwww.two.com"
},
{
"name":"wallpaper-25570",
"url":"wwww.three.com"
},
{
"name":"wallpaper-364251",
"url":"wwww.four.com"
}
]
gatsby-config-js with the following contents:module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `content`,
path: `${__dirname}/src/images`,
},
},
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
],
}
src/components/ComponentA.js with the following contents.import React from 'react';
import { useStaticQuery,graphql } from 'gatsby';
import Img from 'gatsby-image'
import Urls from '../assets/data/Urls.json'
const ComponentA=()=>{
const data=useStaticQuery(graphql`
query AllSponsors {
allFile(filter: {absolutePath: {regex: "/sponsors/"}}) {
edges {
node {
name #name added to match the url
childImageSharp {
fluid(maxWidth: 2000) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`)
return(
<div>
{
data.allFile.edges.map(item=>(
<div>
<Img key={`image_${item.node.name}`} fluid={item.node.childImageSharp.fluid} style={{height:'500px'}}/>
<p key={`image_${item.node.name}`} style={{fontSize:'18px', fontWeight:'bold'}}>
{
Urls.filter(x=>x.name===item.node.name).map(url=>{return url.url}) // returns the url based on the name of the image
}
</p>
</div>
))
}
</div>
)
}
export default ComponentA
/src/pages/index.js and running gatsby develop and opening http://localhost:8000 i'm presented with the following:
Now, the key things to take from your issue.
Feel free to provide feedback, so that we can close this issue or we can continue to work on it.
Thanks for this @jonniebigodes, I had been looking for an example of how to do this all day yesterday. Just used it to match up people listed in a json file with their images in a directory.
@ewalpole no problem glad that my reproduction could be of help.
Your value variable hast this elements:
value.source.edges...
value.url.edges...
There is no value.edges... where you will do a .map on it
If you like to map it 1:1 you can also have a dictonary:
{
"wallpaper-10053":"wwww.one.com",
"wallpaper-1386":"wwww.two.com",
"wallpaper-25570":"wwww.three.com",
"wallpaper-364251":"wwww.four.com"
}
urls[item.node.name]
Hello, @jonniebigodes we bump again, .filter() solves pretty much everything. You are amazing! The picture become more clearer after learned about name value which is new to me. I dug into localhost:8000/__graphiql docs explorer and discover more thing to play around. Thank you for taking your time breaking this down with clear explaination.
On other issues, but related. Sorting map of image files in alphabet order, should I use graphQL's
sort: {order: ASC} method or JS's .sort((a, b) => a.item.node > b.item.node). Any example on sorting file in ascending order would be great.
@muescha
_Your value variable hast this elements:_
value.source.edges...
value.url.edges...
There is no value.edges... where you will do a .map on it
_There is no value.edges... where you will do a .map on it_
I am not sure I understand your question... As explained above, I am able to see both values from separated queries as result from browser console
{source: {鈥, urls: {鈥}
source: {edges: Array(21)}
urls: {edges: Array(4)}
__proto__: Object
I didn't have problem mapping on both queries. I had problem with sharing value from separate queries and map as one whole.
@aprather51 no need to thank, just glad i could be of assistance and help you solve your original issue.
Regarding your related issue.
Me, personally and from my background i lean towards having all of the data a priori and leave React to render to render it/show it. With that i'm more inclined to have a graphql query executed in gatsby-node.js and pass down the data through the use of pageContext, but for this case and my reproduction the same principle can be achieved, leave the component to render the data supplied by the result of a graphql query. I'm going to extend the example i provided earlier to allow sorting the files by ascending order like you asked. Below are the steps taken:
Urls.json to the following:[
{
"name":"wallpaper-10053",
"url":"wwww.one.com"
},
{
"name":"wallpaper-1386",
"url":"wwww.two.com"
},
{
"name":"wallpaper-25570",
"url":"wwww.three.com"
},
{
"name":"batmanvillains",
"url":"www.batmanvillains.com"
},
{
"name":"wallpaper-364251",
"url":"wwww.four.com"
},
{
"name":"chucknorrium",
"url":"www.strongest-element-on-earth.com"
}
]
query AllSponsors {
allFile(sort: {fields: [name], order: ASC}, filter: {absolutePath: {regex: "/sponsors/"}}) {
edges {
node {
name
childImageSharp {
fluid(maxWidth: 2000) {
src
srcSet
}
}
}
}
}
}
Adding the sort:{fields:[name#same as the name below],order:ASC} will order the files ascending.
gatsby develop and opening up a new browser window to http://localhost:8000 will show me the images accordingly as you can see below:


Hope that this small addition to the reproduction provided earlier solves your issue.
Feel free to provide feedback.
Excellent! With every conceived details, this now solve my issues!
thanks @jonniebigodes to give such great advice and fixing this issue for @aprather51
Most helpful comment
@aprather51 I've picked up on your issue and i believe i have a solution for you.
Here are the steps i took to get it working, going to to breakdown into smaller steps:
src/images/sponsors/.Urls.jsoninsrc/assets/datato match your setup, with a slight difference as you can see below:gatsby-config-jswith the following contents:src/components/ComponentA.jswith the following contents./src/pages/index.jsand runninggatsby developand openinghttp://localhost:8000i'm presented with the following:Now, the key things to take from your issue.
Feel free to provide feedback, so that we can close this issue or we can continue to work on it.