Last active
August 12, 2020 18:11
-
-
Save barbaracassani/b47b4827365646b27d220b2d96abd08e to your computer and use it in GitHub Desktop.
Simple gallery in React & Typescript, where images are loaded dynamically from an external list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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