Search code examples
gatsbystrapicloudinary

How can I make Cloudinary image accessible from Strapi for my Gatsby site?


I cannot access Cloudinary images from Strapi for my Gatsby site. I do the following...

  1. Upload an image into Cloudinary.
  2. In the Strapi Media Library, click on the "Upload assets" button.
  3. I choose the "FROM URL" tab, paste the Cloudinary image link, and then upload it into Strapi.
  4. Go to my "Posts" Collection Type in Strapi, and add the new image from the Media Library and then save/publish the post.
  5. In Gatsby (graphql), I write the following...
  query PostSearchQuery {
    allStrapiPost {
      edges {
        node {
          title
          subtitle
          slug
          id
          description
          image {
            localFile {
              childImageSharp {
                gatsbyImageData(
                  layout: FULL_WIDTH
                  placeholder: BLURRED
                  aspectRatio: 1.3
                )
              }
            }
          }
        }
      }
    }
  }

In http://localhost:8000/___graphql, I run it to check that the image data comes through and get this...

            "image": [
              {
                "localFile": {
                  "childImageSharp": {
                    "gatsbyImageData": {
                      "layout": "fullWidth",
                      "placeholder": {
                        "fallback": "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAADAv/aAAwDAQACEAMQAAAB7bkUCRkZAr//xAAbEAADAAIDAAAAAAAAAAAAAAABAgMAEgQRIf/aAAgBAQABBQKabZoezP1eRSYSyNMA5//EABURAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEDAQE/AaU//8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERITH/2gAIAQIBAT8Bk6N6f//EABwQAAEEAwEAAAAAAAAAAAAAAAABAhExEBJBYf/aAAgBAQAGPwLw5iJk2VXNWiz/xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMUFRcYH/2gAIAQEAAT8hoiOWnua93+y1UzHUeQEnPJcx5bH/2gAMAwEAAgADAAAAEIDf/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAIf/aAAgBAwEBPxBppzEm/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERQf/aAAgBAgEBPxC10OqM/8QAHBABAAMAAgMAAAAAAAAAAAAAAQARMSFRQXHw/9oACAEBAAE/ECpYHo6PqC4x2HWiXGFlVBol7SZKQJr9QxioVvjjwT//2Q=="
                      },
                      "images": {
                        "fallback": {
                          "src": "/static/86c19d070d79399eb57c60d31989e521/a3208/you_bible_rvveya_a96c049ce9.jpg",
                          "srcSet": "/static/86c19d070d79399eb57c60d31989e521/926c9/you_bible_rvveya_a96c049ce9.jpg 750w,\n/static/86c19d070d79399eb57c60d31989e521/4b650/you_bible_rvveya_a96c049ce9.jpg 1080w,\n/static/86c19d070d79399eb57c60d31989e521/4c7b3/you_bible_rvveya_a96c049ce9.jpg 1366w,\n/static/86c19d070d79399eb57c60d31989e521/a3208/you_bible_rvveya_a96c049ce9.jpg 1920w",
                          "sizes": "100vw"
                        },
                        "sources": [
                          {
                            "srcSet": "/static/86c19d070d79399eb57c60d31989e521/b1001/you_bible_rvveya_a96c049ce9.webp 750w,\n/static/86c19d070d79399eb57c60d31989e521/a6f88/you_bible_rvveya_a96c049ce9.webp 1080w,\n/static/86c19d070d79399eb57c60d31989e521/36c2a/you_bible_rvveya_a96c049ce9.webp 1366w,\n/static/86c19d070d79399eb57c60d31989e521/1d7d9/you_bible_rvveya_a96c049ce9.webp 1920w",
                            "type": "image/webp",
                            "sizes": "100vw"
                          }
                        ]
                      },
                      "width": 1,
                      "height": 0.7692708333333333
                    }
                  }
                }
              }
            ]

All so far, so good. The image shows up in graphql.

But then when I attempt to display the image using this...

import React from "react"
import { Link } from "gatsby"
import PropTypes from "prop-types"

import Card from "~/components/styled/card"
import Image from "~/components/image"

const PostList = ({ posts, gridCols }) => {
  return (
    <div className={`grid ${gridCols} gap-6`}>
      {posts.map(post => {
        return (
          <Card key={post.id}>
            <Link to={`/posts/${post.slug}`} key={post.id}>
              <Image
                alt="Post Image"
                className="rounded-t-md border-gray-200  border-b"
                image={post.image}
              />
              <div className="px-4 py-6">
                <p>{post.title}</p>
                <p className="text-xs self-end">
                  {post.subtitle}
                </p>
              </div>
            </Link>
          </Card>
        )
      })}
    </div>
  )
}

PostList.propTypes = {
  posts: PropTypes.array,
  gridCols: PropTypes.string,
}

PostList.defaultProps = {
  gridCols: "grid-cols-1 md:grid-cols-3",
}

export default PostList

..with this being the Image component...

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import { GatsbyImage, getImage } from "gatsby-plugin-image"
import PropTypes from "prop-types"

const Image = ({ image, className, alt }) => {
  const data = useStaticQuery(graphql`
    query {
      strapiGlobal {
        placeHolder {
          localFile {
            childImageSharp {
              gatsbyImageData(
                layout: FULL_WIDTH
                placeholder: BLURRED
                aspectRatio: 1.3
              )
            }
          }
        }
      }
    }
  `)

  if (!image) {
    return (
      <GatsbyImage
        className={className}
        image={getImage(data.strapiGlobal.placeHolder.localFile)}
        alt="Placeholder Image"
      />
    )
  }

  return (
    <GatsbyImage
      alt={alt}
      className={className}
      image={getImage(image.localFile)}
    />
  )
}

Image.propTypes = {
  image: PropTypes.object.isRequired,
  className: PropTypes.string,
  alt: PropTypes.string.isRequired,
}

export default Image

...it comes up blank.

Not sure what I'm missing here. I've run gatsby clean before gatsby develop, but the image still doesn't show.

What's strange about this is that in my "Products" Collection Type in Strapi, the images do show up. (That was in the original Gatsby starter I'm using as a template for this site.). In other words, when I add a new Collection Type, my images don't show up in the Gatsby site.

Any help with this would be much appreciated.


Solution

  • I guess the problem is in your getImage helper function. You can omit it and leave your component as:

      return (
        <GatsbyImage
          alt={alt}
          className={className}
          image={image.localFile.childImageSharp.gatsbyImageData}
        />
    

    Because getImage is an optional helper that fetches the image data using the outer node, in your case, this should work.

    If not, check the data that is getting the Image component to spot any leaking.

    Invalid prop 'image' of type 'array' supplied to 'Image', expected 'object'

    Thanks to this warning, and because of the data structure:

     "image": [
                  {
                    "localFile": {
                      "childImageSharp": {
                        "gatsbyImageData": {
                          "layout": "fullWidth",
                          "placeholder": {
                            "fallback": "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAADAv/aAAwDAQACEAMQAAAB7bkUCRkZAr//xAAbEAADAAIDAAAAAAAAAAAAAAABAgMAEgQRIf/aAAgBAQABBQKabZoezP1eRSYSyNMA5//EABURAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEDAQE/AaU//8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERITH/2gAIAQIBAT8Bk6N6f//EABwQAAEEAwEAAAAAAAAAAAAAAAABAhExEBJBYf/aAAgBAQAGPwLw5iJk2VXNWiz/xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMUFRcYH/2gAIAQEAAT8hoiOWnua93+y1UzHUeQEnPJcx5bH/2gAMAwEAAgADAAAAEIDf/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAIf/aAAgBAwEBPxBppzEm/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERQf/aAAgBAgEBPxC10OqM/8QAHBABAAMAAgMAAAAAAAAAAAAAAQARMSFRQXHw/9oACAEBAAE/ECpYHo6PqC4x2HWiXGFlVBol7SZKQJr9QxioVvjjwT//2Q=="
                          },
                          "images": {
                            "fallback": {
                              "src": "/static/86c19d070d79399eb57c60d31989e521/a3208/you_bible_rvveya_a96c049ce9.jpg",
                              "srcSet": "/static/86c19d070d79399eb57c60d31989e521/926c9/you_bible_rvveya_a96c049ce9.jpg 750w,\n/static/86c19d070d79399eb57c60d31989e521/4b650/you_bible_rvveya_a96c049ce9.jpg 1080w,\n/static/86c19d070d79399eb57c60d31989e521/4c7b3/you_bible_rvveya_a96c049ce9.jpg 1366w,\n/static/86c19d070d79399eb57c60d31989e521/a3208/you_bible_rvveya_a96c049ce9.jpg 1920w",
                              "sizes": "100vw"
                            },
                            "sources": [
                              {
                                "srcSet": "/static/86c19d070d79399eb57c60d31989e521/b1001/you_bible_rvveya_a96c049ce9.webp 750w,\n/static/86c19d070d79399eb57c60d31989e521/a6f88/you_bible_rvveya_a96c049ce9.webp 1080w,\n/static/86c19d070d79399eb57c60d31989e521/36c2a/you_bible_rvveya_a96c049ce9.webp 1366w,\n/static/86c19d070d79399eb57c60d31989e521/1d7d9/you_bible_rvveya_a96c049ce9.webp 1920w",
                                "type": "image/webp",
                                "sizes": "100vw"
                              }
                            ]
                          },
                          "width": 1,
                          "height": 0.7692708333333333
                        }
                      }
                    }
                  }
                ]
    

    image is an array of objects so you should pass down the first reference like:

      <Image
        alt="Post Image"
        className="rounded-t-md border-gray-200  border-b"
        image={post.image[0]}
      />
    

    Outside the scope of the question, keep in mind that whether or not you pass an image, your component is always triggering the useStaticQuery and then, is when you choose to render a placeholder image or not. In terms of performance is not optimal because you are always fetching an unnecessary image (if you are passing it).

    You can create a dummy variable that takes the props image data (in case it exists) or the data from the useStaticQuery hook.