GatsbyJS is one of my favourite technologies lately, It has made frontend development enjoyable again, but I've encountered some limitations (Not specific to Gatsby)
recently and it seems others have encountered similar issues. Namely, building a slideshow/carousel/multiple images with
gastbyjs
and gatsby-image
.
TLDR; I built a "slideshow" of lazy loaded images, demo over at gatsby-slides
Disclaimer: This is pretty experimental and hacky and I'm fairly certain it can be improved, critiques are welcome.
Set up Gatsby and Gatsby-Image
Because gatsby
docs are so well done, it's fairly easy to get started and set up with a basic project. From your terminal, type
$ gatsby new gatsby-slide
$ cd gatsby-slide
This creates a new gatsby project (with gatsby-image
already installed) from a starter template and changes directory after gatsby is done setting up files.
Now if we run npm start
and navigate to localhost:8000 we should see our gatsby site up and running.
We're all set to continue!
Querying Multiple Images
So thankfully, the template includes code to already query an image as shown below
//src/image.js
const Image = () => (
<StaticQuery
query={graphql`
query {
placeholder: file(relativePath: { eq: "gatsby-logo.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`}
render={data => <Img fluid={data.placeholder.childImageSharp.fluid} />}
/>
)
This finds the image gatsby-logo.png
and lazy loads it with the
fragment GatsbyImageSharp
, read more about fragments and gatsby-image
here. But how do we
use this to query multiple images? I came across this lil gem while reading the other day, thanks to Kent C. Dodds for writing it.
graphql`
query {
allFile(
sort: { fields: name, order: DESC }
filter: { relativeDirectory: { eq: "slides" } }
) {
edges {
node {
id
name
childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid_withWebp_tracedSVG
}
}
}
}
}
}
Now that we have this query for getting multiple files, let's go ahead and wire this up with good ol hooks.
import { useStaticQuery, graphql } from 'gatsby'
function SlideShow() {
const [index, setIndex] = useState(0)
const { allFile } = useStaticQuery(
graphql`
query {
allFile(
sort: { fields: name, order: DESC }
filter: { relativeDirectory: { eq: "slides" } }
) {
edges {
node {
id
name
childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid_withWebp_tracedSVG
}
}
}
}
}
}
`
)
//Minus 1 for array offset from 0
const length = allFile.edges.length - 1
const handleNext = () =>
index === length ? setIndex(0) : setIndex(index + 1)
const handlePrevious = () =>
index === 0 ? setIndex(length) : setIndex(index - 1)
const { node } = allFile.edges[index]
return (
<div>
<div>
<Img
fluid={node.childImageSharp.fluid}
key={node.id}
alt={node.name.replace(/-/g, ' ').substring(2)}
/>
</div>
<div>
<button onClick={() => handlePrevious()}>Previous</button>
<button onClick={() => handleNext()}>Next</button>
</div>
</div>
)
}
Some additional logic for handling next and previous slide but overall still a simple example.
Conclusion
Through the mystical powers of React Hooks and graphql, we can useStaticQuery
hook as well
as specifying a filter on our allFiles
to query to get all images in the slides
folder (where all the images for the slideshow are, duh Jordan). The result is pretty niffy, check out the demo gatsby-slides.
Did this interest you? Head over to jordnjones.com for more!
Top comments (5)
Thank you Jordan, exactly what I was looking for.
One thing doesn't work for me, maybe someone had a similar issue.
I have three images in my slider. Clicking "next" on the last one, the whole pages goes white and the silder doesn't start from the first image again.
I'm importing the silder as a component into a page.
Help with this is much appreciated.
Thanks
Good job, Jordan! Thanks
Nice one Jordan. Until now, I just used Pixteller to create slideshows. But I'll try your code.
NICE! works like a charm!
awesome content