reactjsgraphqlgatsbygatsby-plugin-mdx

Gatsby: How to insert data from frontmatter (Mdx file) into a component


I have a series of .mdx files that contain the same information but on different sites (ex: title="aswan"; title="rome" etc). These files are located in a folder called "metadata".

metadata folder

mdx file exemple

I need to insert mdx information into a component (OurSites.js) that goes to form the HomePage of the site (index.js).

This is the content of the OurSites.js component:

import React from "react";
import styled from "styled-components";
import Card from "react-bootstrap/Card";
import { Container, Row, Col } from "react-bootstrap";
import Button from "react-bootstrap/Button";
import TitleR from "../Title/TitleR";
import Card1 from "../../metadata/1-home-page/images/1-card.jpg";
import Card2 from "../../metadata/1-home-page/images/2-card.jpg";

const Sites = () => {
  return (
    <Wrapper>
      <section className="section bottom-slant-gray">
        <Container>
          <TitleR title="our sites" />
          <Row xs={1} md={2}>
            <Col>
              <Card>
                <Card.Img variant="top" fluid={true} src={Card1} />
                <Card.Body>
                  <Card.Title>First Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/">
                      go to paths repository
                    </a>
                  </Button>
                  <Card.Text>
                    Collection and georeferencing on GIS platform of most of the
                    historical cartography of Egypt and plans of the main
                    temple/church/basilica complexes
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
            <Col>
              <Card>
                <Card.Img variant="top" src={Card2} />
                <Card.Body>
                  <Card.Title>Second Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/svp">
                      go to spv protocol
                    </a>
                  </Button>
                  <Card.Text>
                    Vectorization of geo-referenced plants on GIS platform using
                    a protocol (SPV) developed by PAThs team members
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
          </Row>
          <Row xs={1} md={2}>
            <Col>
              <Card>
                <Card.Img variant="top" fluid={true} src={Card1} />
                <Card.Body>
                  <Card.Title>First Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/">
                      go to paths repository
                    </a>
                  </Button>
                  <Card.Text>
                    Collection and georeferencing on GIS platform of most of the
                    historical cartography of Egypt and plans of the main
                    temple/church/basilica complexes
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
            <Col>
              <Card>
                <Card.Img variant="top" src={Card2} />
                <Card.Body>
                  <Card.Title>Second Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/svp">
                      go to spv protocol
                    </a>
                  </Button>
                  <Card.Text>
                    Vectorization of geo-referenced plants on GIS platform using
                    a protocol (SPV) developed by PAThs team members
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
          </Row>
          <Row xs={1} md={2}>
            <Col>
              <Card>
                <Card.Img variant="top" fluid={true} src={Card1} />
                <Card.Body>
                  <Card.Title>First Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/">
                      go to paths repository
                    </a>
                  </Button>
                  <Card.Text>
                    Collection and georeferencing on GIS platform of most of the
                    historical cartography of Egypt and plans of the main
                    temple/church/basilica complexes
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
            <Col>
              <Card>
                <Card.Img variant="top" src={Card2} />
                <Card.Body>
                  <Card.Title>Second Step</Card.Title>
                  <Button variant="primary">
                    <a href="https://docs.paths-erc.eu/data/svp">
                      go to spv protocol
                    </a>
                  </Button>
                  <Card.Text>
                    Vectorization of geo-referenced plants on GIS platform using
                    a protocol (SPV) developed by PAThs team members
                  </Card.Text>
                </Card.Body>
              </Card>
            </Col>
          </Row>
        </Container>
      </section>
    </Wrapper>
  );
};

const Wrapper = styled.section`
  a {
    color: rgb(130, 36, 51);
    font-family: "Raleway", sans-serif;
    font-weight: bolder;
    font-size: 0.8rem;
    line-height: 1rem;
    text-transform: uppercase;
    display: swap;
    text-decoration: none;
  }
  a:hover {
    color: rgb(130, 36, 51);
    font-family: "Raleway", sans-serif;
    font-weight: bolder;
    font-size: 0.8rem;
    line-height: 1rem;
    text-transform: uppercase;
    display: swap;
    text-decoration: none;
  }
  button {
    text-align: right;
    margin: 3% 0 3% 0;
    background: rgb(130, 36, 51, 0.2);
    border-color: rgb(130, 36, 51, 0.3);
  }
  button:hover {
    background: none;
    border-color: transparent;
  }
  section {
    padding: 4em 5;
    position: relative;
    z-index: 2;
  }
  .card {
    border: none;
  }
  .card-body {
    text-align: right;
    font-family: "Raleway", sans-serif;
    font-size: 1rem;
    line-height: 1.7rem;
    display: swap;
  }
  .card-title {
    font-weight: bolder;
    text-transform: uppercase;
  }
  .container {
    padding-bottom: 5%;
  }
  section {
    padding: 0;
    position: relative;
    z-index: 2;
  }
  .bottom-slant-gray {
    position: relative;
    padding-bottom: 10%;
    background-color: #f8f9fa;
  }
  .bottom-slant-gray:before {
    content: "";
    width: 100%;
    height: 240px;
    background: #f8f9fa;
    z-index: -1;
    top: 0px;
    background-color: #f8f9fa;
    left: 0;
    position: absolute;
    -webkit-transform: skewY(-6deg);
    -ms-transform: skewY(-6deg);
    transform: skewY(-6deg);
    -webkit-transform-origin: top left;
    -ms-transform-origin: top left;
    transform-origin: top left;
  }
  .row {
    padding-top: 3%;
  }
  .sites-img {
    border-top-left-radius: var(--radius);
    border-top-right-radius: var(--radius);
    height: 19rem;
    z-index: 1;
  }
  .sites-img::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(to bottom right, var(--clr-primary-5), #222);
    opacity: 0.85;
    transition: var(--transition);
  }
`;

export default Sites;

Where there is text, such as in CardText, I would like to insert the contents of mdx files.

Querying the data on Graphql gave this result:

export const query = graphql`
  {
    allMdx(limit: 8, sort: { fields: frontmatter___title, order: ASC }) {
      nodes {
        id
        frontmatter {
          title
          status
          typology
          image {
            childImageSharp {
              gatsbyImageData
            }
          }
        }
        excerpt
      }
    }
  }
`;

This is the content of the index.js page inside which is present also the OurSite.js component:

import * as React from "react";
import Layout from "../components/Layout";
import Slider from "../components/Slider";
import About from "../components/Home/About";
import Methods from "../components/Home/Methods";
import OurSites from "../components/Home/OurSites";
import { graphql } from "gatsby";

// markup
const IndexPage = () => {
  return (
    <Layout>
      <Slider />
      <About />
      <Methods />
      <OurSites />
    </Layout>
  );
};

export const query = graphql`
  {
    allMdx(limit: 8, sort: { fields: frontmatter___title, order: ASC }) {
      nodes {
        id
        frontmatter {
          title
          status
          typology
          image {
            childImageSharp {
              gatsbyImageData
            }
          }
        }
        excerpt
      }
    }
  }
`;

export default IndexPage;

This is what the component looks like:

enter image description here


Solution

  • You have two options:

    With the first option, your queries must go on a page (hence the name) and you need to drill down the props containing your data to each desired component. Because of you already have the query set, you just need to:

    import * as React from "react";
    import Layout from "../components/Layout";
    import Slider from "../components/Slider";
    import About from "../components/Home/About";
    import Methods from "../components/Home/Methods";
    import OurSites from "../components/Home/OurSites";
    import { graphql } from "gatsby";
    
    // markup
    const IndexPage = ({ data }) => {
     console.log("your props.data is inside data: " data); 
     return (
        <Layout>
          <Slider />
          <About />
          <Methods />
          <OurSites sites={data.allMdx.nodes}/>
        </Layout>
      );
    };
    
    export const query = graphql`
      {
        allMdx(limit: 8, sort: { fields: frontmatter___title, order: ASC }) {
          nodes {
            id
            frontmatter {
              title
              status
              typology
              image {
                childImageSharp {
                  gatsbyImageData
                }
              }
            }
            excerpt
          }
        }
      }
    `;
    
    export default IndexPage;
    

    Your queried data (via GraphQL) is inside props.data (destructured as data). You can drill down the site's information by data.allMdx.nodes (which is an array). So in your OurSites component, you only need to get the props (props.sites) and loop through them to display dynamically your data.

    With the useStaticQuery the approach is exactly the same but the data can be stores somewhere else (in a custom hook or in the inner OurSites component).