Search code examples
reactjsgraphqlgatsby

Render image based on page name in React Component


I am pulling an image from Contentful that is supposed to go into a Banner Component. Each page of my site should have a Banner. In Contentful, I gave the Content Model for the Banner Image a slug referring to a page name. Now, in my Gatsby project, I created a component, and inside it I am using a StaticQuery that returns the slug (page name). Using the Banner Component in each individual page, I want to match the page name with the slug. And for example, when I am in the page 'malerei' the image with the slug of 'malerei' (see example of MalereiPage in the second code snipped below) should render in the component. I am unsure how to achieve this but would appreciate any lead on this.

My Component:

import React from 'react'
import { StaticQuery, graphql } from 'gatsby'


function Banner ({ data, props }) {
    return (
        <>
        <StaticQuery
            query={graphql`
              query BannerQuery {
                allContentfulBannerImage {
                    nodes {
                        slug
                        image {
                          id
                          resize(width: 1200) {
                            width
                            height
                            src
                          }
                        }
                    }
                 }
              }
          `}
          render={data => {

              return(
                <div>
                  {data.allContentfulBannerImage.nodes.map((image) => {

                        return (
                            <div key={image.slug}>
                                <img className="mb-5" src={image.image.resize.src} style={{float: "left", width: "100%", height: "90vh", objectFit: "cover"}}/>
                            </div>
                        )
                    })}

                </div>
              )}}
        />
            </>
    )
}


export default Banner

Example of <Banner /> being used in a page:

import React from 'react'
import Layout from '../components/Layout'
import Banner from '../components/Banner'


const MalereiPage = () => (
    <Layout>
        <Banner/>
    </Layout>
)



export default MalereiPage

Solution

  • I think your best option is to use a page query rather than a static query because your banner image will be only fetched once and not each time you want to render a new page.

    That said if each banner image is linked to each page via slug, you can create a specific page query filtered by this slug to get your data.

    Something similar to:

    const MalereiPage = ( { data } ) => (
        <Layout>
          <Banner image={data.allContentfulBannerImage.nodes}/>
        </Layout>
    )
    
    export const query = graphql`
    query getMalereiContent {
      allContentfulBannerImage(filter: {slug: {eq: "malerei"}}) {
        nodes {
          slug
          image {
            id
            resize(width: 1200) {
              width
              height
              src
            }
          }
        }
      }
    }
    `
    
    export default MalereiPage
    

    And:

    function Banner(props) {
      const image = props.image;
      console.log(image);
      image.map((img) => {
        console.log(img.image);
      });
      return (
        <div>
          {image.map((img) => {
            return (
              <div key={img.slug}>
                <img
                  className="mb-5"
                  src={img.image.resize.src}
                  style={{
                    float: "left",
                    width: "100%",
                    height: "90vh",
                    objectFit: "cover",
                  }}
                />
              </div>
            );
          })}
        </div>
      );
    }
    
    export default Banner;
    

    Note: keep in mind that without knowing your schema or your data structure this is an approximation. Test the query at localhost:8000/___graphql

    The idea relies on filtering the page query using the known slug for that page. There, you can fetch all the page data, including the banner image, for that specific page.

    At this point, you only need to pass the image node to your Banner component to render directly the asset, without the use of StaticQuery.