Search code examples
reactjsgraphqlgatsbygatsby-plugin

GraphQL only returning first node on Gatsby site


I'm using gatsby-source-mysql to pull some data from an internal tool where our users are able to create advertisements that can be displayed on our consumer site. I currently have four promos set up for testing, and this is the GraphQL query that I have to pull that data:

query PromoQuery($id: String) {
    allMysqlPromos(filter: { id: { eq: $id } }) {
      edges {
        node {
          ad_title
          ad_filename
          ad_body
          URL_ext
          phone
          id
        }
      }
    }
  }

This is what's being returned. It's getting all four promos, which is exactly what I need.

{
  "data": {
    "allMysqlPromos": {
      "edges": [
        {
          "node": {
            "ad_title": "Buy One, Get One Free",
            "ad_filename": "ad_002910.jpg",
            "ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
            "URL_ext": "/promo-one",
            "phone": "19167137108",
            "id": "mysql__Promos__2910"
          }
        },
        {
          "node": {
            "ad_title": "Buy Two, Get Two Free",
            "ad_filename": "ad_002911.jpg",
            "ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
            "URL_ext": "/promo-two",
            "phone": "19165451660",
            "id": "mysql__Promos__2911"
          }
        },
        {
          "node": {
            "ad_title": "Buy Three, Get Three Free",
            "ad_filename": "ad_002912.jpg",
            "ad_body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam turpis quam venenatis porta sed. Aliquet eget lobortis quam ut dignissim eget quam lobortis. Elementum, at nullam tincidunt viverra pulvinar ac porta sed mauris. Sit leo imperdiet turpis morbi arcu, posuere odio sit.",
            "URL_ext": "/promo-three",
            "phone": "19168243634",
            "id": "mysql__Promos__2912"
          }
        },
        {
          "node": {
            "ad_title": "New Year's Special",
            "ad_filename": "ad_002913.jpg",
            "ad_body": "Our amazing New Year's Special will guarantee you 50% off of 150 doors. If your house is big enough to have 150 doors then you deserve several thousand dollars off.",
            "URL_ext": "/promo-four",
            "phone": "19163654393",
            "id": "mysql__Promos__2913"
          }
        }
      ]
    }
  }
}

However, in the template for the individual promos, I'm getting the same content on all four, and it is only returning data from the first node i.e. all four different promos have 'Buy One, Get One Free' as the main heading etc. Here is my template for the promo pages, including the GraphQL query from above.

/* eslint-disable react/display-name */
import React, { useContext, useEffect } from 'react';

import ShareImage from 'assets/images/one-day-share-slogan.png';
import { SEO } from 'components/seo/SEO';
import { Row } from 'containers/row/Row';
import { CallRail } from 'contexts/callrail-context/CallRailContext';
import { graphql } from 'gatsby';

import { Content } from './promo/content/_Content';
import { CallToAction } from './promo/cta/_CallToAction';
import { Hero } from './promo/hero/_Hero';

export default (props: any) => {
  const document = props.data.allMysqlPromos.edges[0];
  if (!document) return null;

  const { changeNumber } = useContext(CallRail);

  const number = document.node.phone;

  useEffect(() => {
    changeNumber(number);
  });

  console.log(document.node.ad_title);

  return (
    <>
      <SEO
        title={document.node.ad_title}
        desc={document.node.ad_body.substr(0, 150) + '...'}
        banner={ShareImage}
      />
      <Hero document={document.node} />

      <Row>
        <CallToAction />
        <Content>{document.node.ad_body}</Content>
      </Row>
    </>
  );
};

export const query = graphql`
  query PromoQuery($ad_title: String) {
    allMysqlPromos(filter: { id: { eq: $ad_title } }) {
      edges {
        node {
          ad_title
          ad_filename
          ad_body
          URL_ext
          phone
          id
        }
      }
    }
  }
`;

What am I doing wrong, and what do I need to change to get the correct data in for each promo page?


Solution

  • You should pass via context your filter value, in that case, the ad_title field. So, in your gatsby-node.js you should have something like:

    createPage({
      path: `/promo/${URL_ext}`, // or your value
      component: individualPromoComponent, // or your component
      context: {
        ad_title: node.ad_title,
      },
    })
    

    Now, you can use ad_title in your component using $ad_title in:

    export const query = graphql`
      query PromoQuery($ad_title: String) {
        allMysqlPromos(filter: { id: { eq: $ad_title } }) {
          edges {
            node {
              ad_title
              ad_filename
              ad_body
              URL_ext
              phone
              id
            }
          }
        }
      }
    `;