Search code examples
graphqlgatsbynetlify-cmsgatsby-image

graphQL + gatsby: query a field that is Image or mp4


Have a gatsby blog to which I've added a cover image that is either an image (I want that to appear as a Gatsby Image) or mp4 (I want that to appear as html5 video).

The problem is, when I query this field (in my markdown posts, cover: x.mp4 or cover: x.jpg), if it's an mp4 and it doesn't have a property of childImageSharp (error: TypeError: Cannot read property 'fluid' of null).

My query looks like this:

  frontmatter {
    date(formatString: "YYYY")
    title
    cover {
      childImageSharp {
        fluid(maxWidth: 900) {
          ...GatsbyImageSharpFluid_noBase64
          ...GatsbyImageSharpFluidLimitPresentationSize
        }
      }
    }
  }

so my goal is to have some kind of JSX like:

{post.frontmatter.cover.childImageSharp && (
  <Img fluid={post.frontmatter.cover.childImageSharp.fluid} />
)}
{post.frontmatter.cover.childImageSharp ? '' : (
  <video src={post.frontmatter.cover} />
)}

any ideas?


Solution

  • The problem is, when I query this field (in my markdown posts, cover: x.mp4 or cover: x.jpg), if it's an mp4 and it doesn't have a property of childImageSharp (error: TypeError: Cannot read property 'fluid' of null).

    The cover field will be a File node, so you won't be able to get the video src from it directly. If you just want access to the mp4 file (to put inside a video tag), you can query for its publicURL:

      frontmatter {
        date(formatString: "YYYY")
        title
        cover {
          extension
          publicURL
    
          childImageSharp {
            fluid(maxWidth: 900) {
              ...GatsbyImageSharpFluid_noBase64
              ...GatsbyImageSharpFluidLimitPresentationSize
            }
          }
        }
      }
    

    Then in your component:

    {cover.extension === 'mp4'
      ? <video src={cover.publicURL} />
      : <Img fluid={cover.childImageSharp.fluid} />
    )}