Gatsby / Graphql - Can't display img from query - reactjs

Below is my code:
import React from 'react'
import { graphql, useStaticQuery } from "gatsby"
import Img from 'gatsby-image'
const ImageGallery = () => {
const data = useStaticQuery(graphql`
query {
images: allFile(filter: { sourceInstanceName: {eq: "images" }}) {
edges {
node {
relativePath
childImageSharp {
id
fluid {
originalImg
}
}
}
}
}
}
`)
// Filters all the images from "gallery-one"
const galleryImages = data.images.edges.filter(edge =>
edge.node.relativePath.startsWith("gallery-one")
)
console.log(data)
console.log(galleryImages)
return (
<div>
<h1>Gallery One</h1>
{
// Mapping over galleryImages array to display each image
galleryImages.map((image) =>
<div>
// Returns relative path for each image
{image.node.childImageSharp.fluid.originalImg}
// Returns nothing
<Img fluid={image.node.childImageSharp.fluid.originalImg} />
</div>
)
}
</div>
)
}
export default ImageGallery
With the first part in the map, it returns:
/static/3608211e3ce3f78486c9e344b92332d9/5f7bf/20171107_155145.jpg
/static/fccd9cdb1c9b525bfaf9282343d680a6/5f7bf/20171101_103124.jpg
/static/cdcbaebc030e210debc70bdff7a8d539/5f7bf/20171107_155126.jpg
/static/ef8708d7f536bd152c9ce98833d6d871/5f7bf/20171101_103218.jpg
/static/1c3b4e40cb5044e604009935b625fa38/5f7bf/20171101_103138.jpg
One for each image in the 'gallery-one' folder, but I cannot figure out how to get it to display using Gatsby Img.
I feel like this is really close, but I can't seem to figure it out
fluid={image.node.childImageSharp.fluid.originalImg}

Yes, you're almost there.
When you query an image to be displayed using gatsby-image you have 2 options:
Use a GraphQL fragment:
Instead of using originalImg you should use ...GatsbyImageSharpFluid which will provide to the fluid object all information required.
Querying all the data required. In this case you should use:
fluid (maxWidth: 800) {
aspectRatio
src
srcSet
sizes
originalImg
originalName
}
Disclaimer: the default maxWidth is 800px. If you don't set it, it will take the default value.
Once you gathered all the information, it needs to be passed to <Img> removing your originalImg, such as:
fluid={image.node.childImageSharp.fluid}
For further information check Gatsby Image API documentation.

Related

Graphql / Gatsby trying to filter by relative directory

I'm trying to sort images by their parent directory for separate galleries. My directory looks like /images/gallery-one. I think I'm close, but for whatever reason I can't get it to filter by relativePath.
Any help would be greatly appreciated, even just sending me in the right direction.
import React from 'react'
import { graphql, useStaticQuery } from "gatsby"
import Img from 'gatsby-image'
const ImageGallery = () => {
const data = useStaticQuery(graphql`
query {
images: allFile(filter: { sourceInstanceName: {eq: "images" }}) {
edges {
node {
relativePath
childImageSharp {
id
fluid {
originalImg
}
}
}
}
}
}
`)
const galleryImages = data.images.edges.node.filter(img => {
})
console.log(data)
return (
<div>
<h1>Gallery One</h1>
</div>
)
}
export default ImageGallery
That should work. Using your GraphQL query and the following filter statement you get the gallery-one images like this:
data.images.edges.filter(edge =>
edge.node.relativePath.startsWith("gallery-one")
)
(Keep in mind that edges is a list where each item contains a node and that relativePath will be e.g. gallery-one/b.png)
Here's my image directory structure:

Can't load in images from Contentful using GatsbyJS

First time posting here, but I've been struggling with this for a few days now.
Basically I have a graphQL query that pulls in product data from contentful and then display it on a GatsbyJS page. The query correctly displays for the title, price, and description of the product but it wont load in the image. Unfortunately I keep receiving errors such as:
"TypeError: Cannot read property '0' of undefined"
or
Cannot read property 'src' of undefined. (When changing the query to look at the src of an image. When I do this method, the url does have a value according to GraphiQL)
here's the code for the page I am currently working on:
import React from 'react'
import { graphql } from 'gatsby'
import Img from 'gatsby-image'
import Layout from '../components/Layout'
import './shop.scss'
const Shop = ({ data }) => {
return (
<Layout>
<section>
{data.allContentfulProducts.edges.map( ({ node }) => (
<article key={node.id}>
<Img
fluid={node.images.fluid}
/>
<p>{node.productName}</p>
</article>
))}
</section>
</Layout>
)
}
export const productQuery = graphql`
query {
allContentfulProducts {
edges {
node {
id
productName
images {
fluid {
...GatsbyContentfulFluid
}
}
}
}
}
}
`
export default Shop
I think there is a problem with you graphQL Query. Try this one:
export const productQuery = graphql`
query {
allContentfulProducts {
edges {
node {
id
productName
image {
fluid {
src
...GatsbyContentfulFluid
}
}
}
}
}
}
`
If this query is not helping please show us the structure of your contentful assets.

How do you query and display a folder of multiple images using GatsbyJS and GraphQL

I'm trying to query all images in a folder and display them in a card grid with tailwindCSS and gatsby-image. I've been able to query and display one image, but when I try to do it with a folder of images, I get the error "TypeError: Cannot read property 'edges' of undefined" even though the query works in the GraphQL explorer. I've read the docs, looked at other tutorials, and tried it so many different ways now and can't figure out what's wrong. Any help is greatly appreciated!
import React from "react";
import { graphql } from "gatsby";
import Img from "gatsby-image";
import Layout from "../components/layout";
import SEO from "../components/seo";
const ArtPage = props => (
<Layout>
<SEO
keywords={[`art`, `paint`, `draw`]}
title="Art"
/>
<div class="flex flex-wrap mt-2 mx-1">
{props.artImages.edges.map(img => (
<div class="w-full md:w-1/2 lg:w-1/2 px-2 my-2">
<div className="rounded overflow-hidden shadow-lg">
<Img
className="w-full"
fluid={img.node.childImageSharp.fluid}
/>
</div>
</div>
))}
</div>
</Layout>
)
export default ArtPage;
export const query = graphql`
query artImages {
allFile(filter: { relativePath: { regex: "/art/.*.png/" } } )
{
edges {
node {
relativePath
name
childImageSharp {
fluid(maxWidth: 500) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`;
Debugging such an issue is always difficult. Since you stated that your query is correct in GraphiQL you probably made a mistake referencing the right attributes in the GraphQL tree. undefined is an indicator that you reference an object that does not exist.
The secret weapon for debugging this issue is actually console.log(graphQlobject). Print the object in your browser and try acessing the attributes until you get it right.
I will give you my HeaderSupplier component that I use in my project and reference the important bits with comments:
import React from "react";
import { graphql, useStaticQuery } from "gatsby";
import GatsbyImage from "gatsby-image";
import styled from "styled-components";
import { pickRandomly } from "../util/utilityFunctions";
/**
* Returns one random image header.
* Uses GatsbyImage and GraphQL to load images.
* #see https://www.orangejellyfish.com/blog/a-comprehensive-guide-to-images-in-gatsby/
*/
const HeaderSupplier = () => {
const { allFile } = useStaticQuery(graphql`
query {
allFile(filter: {
extension: {regex: "/(jpg)|(jpeg)|(png)/"},
sourceInstanceName: {eq: "headers"}})
// filter by sourceInstanceName, see the gatsby-config.js,
// this way you get exactly the files you need without complicated regex statements
{
edges {
node {
childImageSharp {
fluid(maxWidth: 150, quality: 100) {
originalName
...GatsbyImageSharpFluid
}
}
}
}
}
}`);
// use console.log for debugging and correctly navigating the graphQL tree
console.log(allFile);
const header = pickRandomly(allFile.edges);
const { fluid } = header.node.childImageSharp;
// make sure you reference the correct objects
// if you get undefined you made a mistake navigating the GraphQL tree
return (
<GatsbyImage fluid={fluid} alt={fluid.originalName} />
);
};
export default HeaderSupplier;
The source instance in the gatsby-config.js:
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/src/components/library/headers`,
name: "headers",
},
I was using props.artImages instead of props.data.artImages ooooooops

Trying to Display Additional Image Thumbnails Below Main Featured Product Image

Can't get files from Moltin API to display under main product image
Using this repo: https://github.com/moltin/gatsby-demo-store and updating
#moltin/gatsby-source-moltin to 1.3.1 I have tried expanding the product
node schema to include relationships as per Moltin API documentation then
referencing this in a new component but no additional images render.
Had a look at other implementations i.e. Gatsby Store example which uses
Thumbnails and could get a tiny clickable thin purple strip rendering but with no image. The store uses Shopify and localFile storage for image rendering so this use case is not applicable.
```
import React, { useContext, useEffect, useReducer, useState } from 'react'
import { graphql, withPrefix } from 'gatsby'
import SEO from '../components/SEO'
import Photo from '../components/Photo'
import Badge from '../components/Badge'
import AddToCart from '../components/AddToCart'
import { Shopkit } from '../shopkit'
import Img from 'gatsby-image'
const {
meta: { display_price }
} = product
return (
<React.Fragment>
<SEO
type="product"
title={product.meta_title || product.name}
description={product.meta_description || product.description}
image={withPrefix(product.mainImage.childImageSharp.fixed.src)}
/>
<div className="flex flex-wrap md:bg-grey-light">
<div className="py-2 md:py-5 md:px-5 w-full lg:w-1/2">
<div className="sticky pin-t">
<Photo
src={product.mainImage}
alt={product.main_image_alt_text || product.name}
/>
<Img
src={product.relationships.files.data.id}
alt=""
/>
</div>
</div>
......
.....
....
</React.Fragment>
)
}
export const query = graphql`
query($id: String!) {
product: moltinProduct(id: { eq: $id }) {
id
slug
name
description
sku
mainImage {
childImageSharp {
fixed(width: 560) {
...GatsbyImageSharpFixed
}
}
publicURL
}
meta {
display_price {
without_tax {
formatted
}
}
}
manage_stock
meta_title
meta_description
on_sale
bulb
bulb_qty
material
finish
max_watt
relationships {
main_image {
data {
id
}
}
files {
data {
type
id
}
}
}
`
export default ProductPage
```
Would like to get small thumbnail rending below main product image. Console
error message when using Img component: Uncaught TypeError: Cannot read
property 'src' of undefined.
gatsby-source-moltin adds a images field to the product schema which you can query like so:
images {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
I put together an example on CodeSandbox.

What is the best way to display all pictures of a directory in a Gatsby project using React?

I am using GatsbyJS starter https://www.gatsbyjs.org/starters/codebushi/gatsby-starter-forty/ and have a need to display all pictures from a directory on a page. Gatsby's recommended way to import media is to use import statement, but it results in hashes added to the file names after the build. For example:
/static/pic09-d59e4b49832baeb9c62a7a9d6c070f8c.jpg
If I retrieve all filenames from a directory and try to create <img> elements with src={fileName} it results in empty images, because file names does not match with the ones from the server already with hashes appended.
Please recommend an elegant solution on how to go through this. My backup plan is to put everything to the static directory where hashes are not being added, but it is not recommended way by Gatsby documentation: https://www.gatsbyjs.org/docs/static-folder/
This is what I have now:
import React from 'react'
import Layout from '../components/layout'
class Gallery extends React.Component {
render() {
const images = [];
const req = require.context('../assets/images/signboards', false);
req.keys().forEach(function (key) {
images.push(key.substr(1));
});
return (
<Layout>
<div id="main">
<section className="spotlights">
<section>
{images.map((image) => {
return (
<div className="image">
<img src={'../assets/images/signboards' + image} alt="" />
</div>
)
})}
</section>
</section>
</div>
</Layout>
)
}
}
export default Gallery;
Thank you
Note: this answer assumes you have already installed gatsby-source-filesystem, gatsby-transformer-sharp and gatsby-plugin-sharp.
You can use a graphql page query to get all of the files of a certain extension, in a certain folder by filtering allFile with a combination of regular expression matchers.
Then you can loop through the resulting edges and use gatsby-image to display the image.
import React from "react"
import { graphql } from "gatsby"
import Img from 'gatsby-image'
const IndexPage = ({data}) => (
<>
{data.allFile.edges.map(edge => {
return <Img fluid={edge.node.childImageSharp.fluid} />
})}
</>
)
export default IndexPage
export const indexQuery = graphql`
query AssetsPhotos {
allFile(filter: {extension: {regex: "/(jpg)|(jpeg)|(png)/"}, dir: {regex: "/assets/images/signboards"}}) {
edges {
node {
id
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
You can use the gatsby-source-filesystem plugin.
install the plugin:
npm install --save gatsby-source-filesystem
Register a folder or other filters(extenssion, etc.) in the gatsby.config.js and give it a name.
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/pages/type1`,
name: 'data',
},
},
Then build query like this, in the component:
{
allFile(filter: { sourceInstanceName: { eq: "data" } }) {
edges {
node {
extension
dir
modifiedTime
}
} }}
You can have many of these "registrations" providing different data(folder, extension, etc.)

Resources