I am working on a Gatsby project.
I want to keep a folder of employees, each employee has it's own folder like src/staff/hanna-rosenfeld/...
containing a index.mdx
and a image file.
I want to source the staff's names and images to use in a component.
my gatsby-config:
module.exports = {
siteMetadata: {
title: "Musikschule Weimar",
},
plugins: [
"gatsby-plugin-image",
"gatsby-plugin-sharp",
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages/`,
},
},
{
resolve: "gatsby-source-filesystem",
options: {
name: `staff`,
path: `${__dirname}/src/staff`,
}
},
"gatsby-plugin-mdx",
"gatsby-transformer-sharp",
"gatsby-transformer-remark",
`gatsby-remark-images`,
],
};
I already got the component that is doing the dropdown working:
import * as React from 'react'
import { useState, useEffect } from "react"
import { useStaticQuery, graphql } from 'gatsby'
import { BiChevronDown } from "react-icons/bi";
import StaffList from "./StaffList"
const rows = [
{
id: 1,
title: "Verantwortliche",
},
{
id: 2,
title: "Lehrende der Zupfinstrumente",
instrument: "zupfinstrumente"
},
{
id: 3,
title: "Lehrende der Blechblasinstrumente",
},
{
id: 4,
title: "Lehrende des Tasteninstruments",
},
{
id: 5,
title: "Lehrende des Gesangs",
},
{
id: 6,
title: "Lehrende des Schlagzeugs",
},
{
id: 7,
title: "Lehrende des Akkordeons",
},
{
id: 8,
title: "Lehrende der Musiktheorie",
},
{
id: 9,
title: "Lehrende der Früherziehung",
}
]
class DropDownRows extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<div className="dropdown-rows">
{rows.map(row => (
<div key={row.id}>
<div className="row">
<div className="col">{row.title}</div>
<div className="col">
<BiChevronDown
onClick={this.handleClick}
style={{float: "right"}}/>
</div>
<div>
</div>
</div>
{this.state.isToggleOn ? <StaffList /> : ''}
</div>
))}
</div>
)
}
}
export default DropDownRows
src/staff/hanna-rosenfeld/index.mdx
---
title: Hanna Rosenfeld
featuredImage: ./Foto_05.jpg
---
Hi, mein Name ist Hanna und ich bin ein full time web developerin.
my StaffList component:
import * as React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import { GatsbyImage, getImage } from "gatsby-plugin-image"
function StaffList({ data }) {
return(
<StaticQuery
query={graphql`
query staffQuery {
allMdx {
edges {
node {
id
body
frontmatter {
title
featuredImage {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
}
`}
render={data => (
<div>
<h1>{data.allMdx.edges.map(edge => <h1 key={edge.node.id} data={edge.node}>{edge.node.frontmatter.title}</h1>)}</h1>
<GatsbyImage alt='some alt text' image={getImage(data.allMdx.edges.map(edge => edge.node.frontmatter.featuredImage))} />
</div>
)}
/>
)
}
export default StaffList
Querying for featuredImage
works in graphiql, but i cannot get the image to show.
Console output:
"Warning: Failed prop type: The prop image is marked as required in GatsbyImage, but its value is undefined."
The current state of the component on the site is this:
Getting the names to show up only in their category is another problem, for now I just want the images to show.
Thank you for any insight on a possible solution in advance.
There are a few things to comment on here:
The render structure is weird. You should do a loop through your data, as you are doing to display the h1
but at the same time, you can take advantage of the loop to display the image of each employee.
In addition, you are using a Gatsby Image v2 GraphQL query structure (gatsby-image
) while the render component (GatsbyImage
) is from v3 (gatsby-plugin-image
). I'd recommend reading the migration guide.
To summarize, when you query for fluid
or fixed
images as you do while using the ...GatsbyImageSharpFluid
fragment you are querying a v2 structure and the render component should be Img
(from gatsby-image
), that is accepting a fixed
or a fluid
image. However, when you use a GatsbyImage
component, the passed prop should be a image
(no matter if it's fixed or fluid). So, you have conflicting plugins and structures. You should get rid of one of them and use the corresponding structure. To recap:
fixed
or fluid
GraphQL query: v2 structure, the render component is Img
GatsbyImage
component: v3 structure. I will base my answer on that assuming that you will migrate to v3 (v2 is deprecated).The issue rises up because as I said,GatsbyImage
is expecting an image
prop while you are passing a loop at and a wrong query data at:
<GatsbyImage alt='some alt text' image={getImage(data.allMdx.edges.map(edge => edge.node.frontmatter.featuredImage))} />
Use something simpler as:
<div>
{data.allMdx.edges.map(edge => (
<article>
<h1 key={edge.node.id}>{edge.node.frontmatter.title}</h1>
<GatsbyImage alt='some alt text' image={getImage(edge.node.frontmatter.featuredImage)} />
</article>
))}
</div>
When you end the migration, the full snippet should look like:
import * as React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import { GatsbyImage, getImage } from "gatsby-plugin-image"
function StaffList({ data }) {
return(
<StaticQuery
query={graphql`
query staffQuery {
allMdx {
edges {
node {
id
body
frontmatter {
title
featuredImage {
childImageSharp {
gatsbyImageData(
width: 200
placeholder: BLURRED
formats: [AUTO, WEBP, AVIF]
)
}
}
}
}
}
}
}
`}
render={data => (
<div>
{data.allMdx.edges.map(edge => (
<article>
<h1 key={edge.node.id}>{edge.node.frontmatter.title}</h1>
<GatsbyImage alt='some alt text' image={getImage(edge.node.frontmatter.featuredImage)} />
</article>
))}
</div>
)}
/>
)
}
export default StaffList
Check the opening/closing brackets and to clean the cache while changing the data sources by running gatsby clean
.