Rendering Contentful single media type from list in React

Viewed 34

I'm trying to pull in data from my projects posts into another page to display selected projects and content. Within the project posts themselves (it was setup by another dev) they have a list of media types such as singleMedia, bannerMedia, accordionMedic etc, the way this is displayed on the project page is using a switch statement to detect what type of content is used in the array.

Within my page I only want to see the singleMedia type of content as that is just the imagery/videos, but when I try and pull in the data although I have console.log'd the array and can see all of the url's and content, my app is still saying Cannot read properties of undefined (reading 'file'). In both my console log and GraphiQL query I can see all of the data I need, but it's not being picked up in my app for some reason.

Below is my array map function, I have used the singleMedia checker to try and filter out any other mediaType, the array is within an array if that helps:

  {value.mainContent.map((block) => (
         <Reveal
              fraction={ANIMATION.revealFraction}
              keyframes={customReveal}
              triggerOnce
         >
              {block.singleMedia && block.singleMedia.fluid ? (
                     <Img key={block.id} fluid={block.singleMedia.fluid} />
              ) : (
                     <Video
                         key={block.id}
                         autoPlay={true}
                         loop={true}
                         muted={true}
                         playsInline
                         src={block.singleMedia.file.url}
                     />
              )}
         </Reveal>
      )
    )}

And below is my GraphQL Query:

    mainContent {
      ... on Node {
        ... on ContentfulProjectSingleMedia {
          id
          internal {
            type
          }
          singleMedia: media {
            file {
              url
            }
            fluid(maxWidth: 1440, resizingBehavior: SCALE) {
              ...GatsbyContentfulFluid
            }
          }
        }
      }
    }
1 Answers

The question lacks of implementation details but it looks like at some point of the React lifecycle, file is null hence the code breaks. Likewise, it seems that you had some rehydration issue in there.

I'd suggest something like:

  {value.mainContent.map((block) => (
         <Reveal
              fraction={ANIMATION.revealFraction}
              keyframes={customReveal}
              triggerOnce
         >
              {block.singleMedia && block.singleMedia.fluid ? (
                     <Img key={block.id} fluid={block.singleMedia.fluid} />
              ) : (
                     <Video
                         key={block.id}
                         autoPlay={true}
                         loop={true}
                         muted={true}
                         playsInline
                         src={block?.singleMedia?.file?.url}
                     />
              )}
         </Reveal>
      )
    )}

In the same way, check if all singleMedia elements contains a file field filled.

Ideally, you should add a safeguard to avoid render null like the coalescent null operator does (?).

Related