If you want to see the source code, it's available here: Source Code
And to view the deployed site, click on this link: Deployed Site
The goal I'm aiming for is quite simple and direct.
Initially, I used a query to load all the image files from the `images` folder:
const data = useStaticQuery(graphql`
query {
allFile(
filter: {
extension: { regex: "/(jpg)|(jpeg)|(png)/" }
sourceInstanceName: { eq: "images" }
}
) {
edges {
node {
childImageSharp {
fluid(maxWidth: 800, quality: 95) {
aspectRatio
src
srcSet
originalName
srcWebp
srcSetWebp
sizes
}
}
}
}
}
}
Subsequently, there's a `gallery` component that arranges these images into three groups, allowing navigation between them using `project1`, `project2`, and `project3`.
const Gallery = ({ minWidth }) => {
let refs = {}
const allPics = Image().map(({ childImageSharp }, i) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
refs[i] = useRef(null)
childImageSharp.index = i
return childImageSharp
})
const firsload = allPics.slice(0, 5)
const secload = allPics.slice(5, 10)
const third = allPics.slice(10)
const [imgs, setImgs] = useState(firsload)
const thumbnails = imgs.map(img => img.fluid.srcSet.split(" ")[0])
return (
<>
<ProjectsContainer>
<Project
onClick={() => {
setImgs(firsload)
}}
>
Project 1.
</Project>
<Project
onClick={() => {
setImgs(secload)
}}
>
Project 2.
</Project>
<Project
onClick={() => {
setImgs(third)
}}
>
Project 3.
</Project>
</ProjectsContainer>
<Mansory gap={"0em"} minWidth={minWidth}>
{imgs.map((img, i) => {
return (
<PicContainer key={img.index}>
<Enlarger
src={thumbnails[i]}
enlargedSrc={img.fluid.src}
index={img.index}
orderIndex={i}
onLoad={() => {
refs[img.index].current.toggleOpacity(1) <-- use ref to keep track of every Enlarger
}}
ref={refs[img.index]}
/>
</PicContainer>
)
})}
</Mansory>
</>
)
}
Each `Enlarger` element rendered by the `Gallery` represents a zoom image component.
import Img from "react-image-enlarger"
class Enlarger extends React.Component {
state = { zoomed: false, opacity: 0 } <--- initially every image's opacity is 0, then it shows up by being toggled opacity 1
toggleOpacity = o => {
this.setState({ opacity: o })
}
render() {
const { index, orderIndex, src, enlargedSrc, onLoad } = this.props
return (
<div style={{ margin: "0.25rem" }} onLoad={onLoad}> <-- where we toggle the opacity when the element is onloaded
<Img
style={{
opacity: this.state.opacity,
transition: "opacity 0.5s cubic-bezier(0.25,0.46,0.45,0.94)",
transitionDelay: `${orderIndex * 0.07}s`,
}}
zoomed={this.state.zoomed}
src={src}
enlargedSrc={enlargedSrc}
onClick={() => {
this.setState({ zoomed: true })
}}
onRequestClose={() => {
this.setState({ zoomed: false })
}}
/>
</div>
)
}
}
I have specifically indicated in the code snippet where I implemented the sequential fade-in animation by utilizing `ref` to control each `Enlarger` element's `toggleOpacity` method.
This code functions perfectly on localhost, during development phase. Feel free to check out the codesandbox link above to observe it in action. However, the issue arises only after deployment of the page. When you visit the deployed version (Deployed Version), you may notice that upon initial loading of the page, some images are missing due to their opacity still being at 0. This occurs because the line `refs[img.index].current.toggleOpacity(1)` may not be triggered when the images are loaded. Strangely enough, during navigation between projects, the animation and opacity changes work flawlessly with no issues. Yet, upon page refresh, the problem resurfaces.
I've been grappling with this dilemma for days without success in identifying the root cause. Even though I utilized ZEIT Now for deploying the site, switching to Netlify did not eradicate the problem either.