问题
So I'm very new to Gatsby, react, GraphQL, etc. In the past I've used pure CSS, HTML, and javascript to make my sites. Although, I was interested in Gatsby and the capabilities of it, so I decided to challenge myself and learn it.
I'm putting together a portfolio site for myself and for ease of updating, I would like to be able to add new projects through creating new folders, running a build script, and dropping the built site into my FTP.
This is how my folder structure for projects is set up:
-src
--projects
---1-daido-moriyama
----1-dm-frontcover.jpg
----2-dm-spread.jpg
----3-dm-backcover.jpg
----project-metadata.md
[...]
---2-lunch-from-a-care-package
----1-lf-wordmark.png
----2-lf-logo.png
----3-lf-poster.jpg
----project-metadata.md
[...]
The site is a single page, so no need to create new pages for each project. I just have them sorted into numbered folders because that would be the easiest to update for myself.
Ideally I would want to take the title and description from each project's markdown file, and put the title in an h3, the description in a p, and then display the images in a div, which when styled will become a carousel.
Mockup of the design
My current progress
I've been running some tests and have been able to access the markdown files using allMarkdownRemark, and the images using allImageSharp. It was hacky, but it worked, the only problem is that it was displaying all of the images, and not just the images needed for each project. Say, I have 8 images in a project, and 5 in another, it would display all 13 images.
Is there a way to do what I'm trying to do with Gatsby? Or should I just give up and move back to Jekyll…
gatsby-config.js:
module.exports = {
siteMetadata: {
title: 'J.C.R.'
},
plugins: [
'gatsby-plugin-react-helmet',
'gatsby-plugin-sass',
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'projects',
path: `${__dirname}/src/projects/`
}
},
'gatsby-transformer-remark',
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
`@dream-bit-de/gatsby-plugin-better-page-tree`
]
}
gatsby-node.js:
const path = require('path')
module.exports.onCreateNode = ({ node, actions}) => {
const {createNodeField} = actions
if (node.internal.type === 'MarkdownRemark') {
const slug = path.basename(path.dirname(node.fileAbsolutePath, '.md'))
createNodeField({
node,
name: 'slug',
value: slug
})
}
}
Work component:
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image'
const Work = () => {
const data = useStaticQuery(graphql`
query {
allMarkdownRemark(
sort: { order: ASC, fields: [frontmatter___position]}
) {
edges {
node {
frontmatter {
title
description
}
fields {
slug
}
}
}
}
allFile (
filter: {
ext: {eq: ".jpg"}
},
sort: {
order: ASC,
fields: [relativePath]
}
) {
edges {
node {
relativePath
relativeDirectory
name
ext
id
base
}
}
}
}
`)
console.log(data)
return (
<div id="work">
<ol>
{data.allMarkdownRemark.edges.map((edge) => {
return (
<li class={edge.node.fields.slug}>
<h3>{edge.node.frontmatter.title}</h3>
<p>{edge.node.frontmatter.description}</p>
{data.allFile.edges.map((edge) => {
return (
<img src={`../projects${edge.node.relativeDirectory}/${edge.node.name}-${edge.node.base}${edge.node.ext}`}></img>
)
})}
</li>
)
})}
</ol>
</div>
)
}
export default Work
index.js:
import React from 'react'
import Head from '../components/head'
import Info from '../components/info'
import Work from '../components/work'
import '../styles/index.scss'
const indexPage = () => {
return (
<div>
<Head/>
<Info/>
<Work/>
</div>
)
}
export default indexPage
回答1:
I should dive deeper in the project to fully understand how you could handle that directly with the graphql query, but a short fix would be to filter out the images not related to the project.
{data.allFile.edge0s.filter((item) => item.name.includes(edge.node.frontmatter.id).map((edge) => {
return (
<img src={`../projects${edge.node.relativeDirectory}/${edge.node.name}-${edge.node.base}${edge.node.ext}`}></img>
)
})}
You will need to add a specific id on the name of your files related to the project so when you fetch them you filter out the one not related.
To be better, you could maybe format your imageSchema and add a specific property to handle the case so you won't need to format the image name and then instead of .includes() you could do item.myProperty === myCustomSchemaProperty.
回答2:
It's much easier than you've tried so far. I would recommend using gatsby-image since all the images belong to the Gatsby ecosystem when you add the following:
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'projects',
path: `${__dirname}/src/projects/`
}
},
Gatsby internally will parse everything inside /src/projects/
and will create nodes to make the schema available for GraphQL, so:
{
allFile(filter: {extension: {eq: "jpg"}}) {
edges {
node {
childImageSharp{
fluid{
...GatsbyImageSharpFluid
}
}
}
}
}
}
Then in your component just:
{data.allFile.edges.map((edge) => {
return <Img fluid={edge.childImageSharp.fluid} />
})}
来源:https://stackoverflow.com/questions/64935654/how-to-use-gatsby-to-display-a-folder-of-images-and-markdown-files