Simple gallery in React & Typescript, where images are loaded dynamically from an external list
import React, { Reducer, useRef, useEffect, useReducer, useState } from "react"; | |
import images, { count } from "./images"; | |
import Button from "./Button"; | |
interface State { | |
count: number; | |
} | |
interface Action { | |
type: "increment" | "decrement"; | |
} | |
function reducer<R extends Reducer<State, Action>>( | |
state: State, | |
action: Action | |
) { | |
switch (action.type) { | |
case "increment": | |
return { count: state.count >= count - 1 ? 0 : state.count + 1 }; | |
case "decrement": | |
return { count: state.count <= 1 ? count - 1 : state.count - 1 }; | |
default: | |
return state; | |
} | |
} | |
function Gallery() { | |
const [imageDisplayed, dispatchChangeImage] = useReducer(reducer, { | |
count: 0, | |
}); | |
const [imagesLoaded, setImageLoaded] = useState(false); | |
const availableImages = useRef([]); // <-- store a reference to the image modules | |
useEffect(() => { // <-- useEffect to load the images as modules | |
Promise.all( | |
images.map((img) => { | |
return import(`./images/${img.url}`); | |
}) | |
).then((images: any) => { | |
availableImages.current = images.map((img: any) => { | |
return img.default; | |
}); | |
setImageLoaded(true); | |
}); | |
}, []); // <-- execute only once by passing empty deps array | |
return ( | |
<> | |
{imagesLoaded && ( | |
<figure> | |
<img | |
src={availableImages.current[imageDisplayed.count] || ""} | |
height={400} | |
width={400} | |
alt={images[imageDisplayed.count].alt} | |
/> | |
<figcaption>{images[imageDisplayed.count].caption}</figcaption> | |
</figure> | |
)} | |
<Button | |
text="Backwards" | |
onClick={dispatchChangeImage.bind(null, { | |
type: "decrement", | |
})} | |
/> | |
<Button | |
text="Forward" | |
onClick={dispatchChangeImage.bind(null, { | |
type: "increment", | |
})} | |
/> | |
</> | |
); | |
} | |
export default Gallery; |
const images = [ | |
{ | |
url: "20_02.jpg", | |
caption: "Pier", | |
alt: "Pier", | |
}, | |
{ | |
url: "20_05.jpg", | |
caption: "Solitary tree", | |
alt: "Tree", | |
}, | |
{ | |
url: "20_07.jpg", | |
caption: "Sausage dog", | |
alt: "Sausage dog", | |
}, | |
{ | |
url: "20_17.jpg", | |
caption: "Daffodils", | |
alt: "Daffodils", | |
}, | |
{ | |
url: "20_21.jpg", | |
caption: "Branches and flowers", | |
alt: "Branches and flowers", | |
}, | |
]; | |
export default images; | |
export const count = images.length; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment