如何在Gatsby组件中将React props传入GraphQL查询?
Alright, let's get this sorted out! The issue you're hitting is a key behavior of Gatsby's StaticQuery — it runs at build time, which means it can't accept dynamic values like props.author as query parameters. Static queries are fixed once your site is built, so we need a different approach here.
Solution 1: Fetch all authors first, filter in the component (best for reusable components)
Since you want this to be a reusable component, the best approach is to use useStaticQuery (the hook-based version of StaticQuery) to fetch all author profiles at build time, then filter the data to match the props.author value passed into the component.
Here's your updated AboutAuthor.js:
import React from "react"; import { useStaticQuery, graphql } from "gatsby"; import Img from "gatsby-image"; export default (props) => { // Fetch all author entries from your markdown files const data = useStaticQuery(graphql` query { allMarkdownRemark(filter: { frontmatter: { name: { ne: null } } }) { nodes { html frontmatter { name profileImage { childImageSharp { fluid(maxWidth: 800) { ...GatsbyImageSharpFluid } } } } } } } `); // Find the matching author using the passed prop const author = data.allMarkdownRemark.nodes.find( node => node.frontmatter.name === props.author ); // Handle cases where the author isn't found (optional but good practice) if (!author) { return <div>Author information not available</div>; } return ( <div> <p>Testing Name: {props.author}</p> {/* Remove this once confirmed working */} <Img fluid={author.frontmatter.profileImage.childImageSharp.fluid} alt={`${author.frontmatter.name}'s profile`} /> <div> <span>{author.frontmatter.name}</span> <div dangerouslySetInnerHTML={{ __html: author.html }} /> </div> </div> ); };
Why this works:
useStaticQuerypulls all author data once during the build process, so there's no runtime overhead.- We use JavaScript's
find()method to match the passedprops.authorto the correct author entry after fetching all data. - The component stays fully reusable — you can drop it anywhere in your site and just pass the
authorprop to get the right profile.
Solution 2: Use Page Queries (for page-specific components)
If this component was only going to be used on individual blog post pages, you could fetch the author data directly in the page's query (which supports dynamic variables) and pass the pre-fetched data to the component. But since you want a reusable component, this is less ideal, but here's how it would look for context:
// Example Blog Post Page (e.g., src/templates/blog-post.js) import React from "react"; import { graphql } from "gatsby"; import AboutAuthor from "../components/AboutAuthor"; export default ({ data }) => { const post = data.post; const author = data.author; return ( <div> <h1>{post.frontmatter.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.html }} /> {/* Pass pre-fetched author data to the component */} <AboutAuthor authorData={author} /> </div> ); }; // Page Query with dynamic variable for author name export const query = graphql` query($authorName: String!) { post: markdownRemark(frontmatter: { author: { eq: $authorName } }) { html frontmatter { title author } } author: markdownRemark(frontmatter: { name: { eq: $authorName } }) { html frontmatter { name profileImage { childImageSharp { fluid(maxWidth: 800) { ...GatsbyImageSharpFluid } } } } } } `;
This works because page queries can accept variables (like $authorName from your page context), but it ties the author data fetching to the page rather than keeping the component self-contained.
Final Notes:
Make sure your markdown files for authors all have a name field in their frontmatter (which you already confirmed works with hardcoded values). The filter { frontmatter: { name: { ne: null } } } in Solution 1 just ensures we only pull entries that actually have an author name set.
内容的提问来源于stack exchange,提问作者Brad Stewart

