Last active
July 10, 2022 14:39
-
-
Save RichardMarks/f941b813e1836f8552aea226d0f90f87 to your computer and use it in GitHub Desktop.
React Hooks Toast Example
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
.toasts-container { | |
position: fixed; | |
z-index: 65535; | |
right: 0; | |
max-width: 250px; | |
display: flex; | |
flex-direction: column-reverse; | |
} | |
.toasts-container > .toast-container { | |
margin-bottom: 10px; | |
} | |
.toasts-container:last-child { | |
margin-bottom: 0; | |
} | |
.toast-container { | |
visibility: hidden; | |
position: relative; | |
z-index: 65535; | |
right: -1000px; | |
background-color: skyblue; | |
border: 2px solid black; | |
border-radius: 10px; | |
padding: 10px; | |
max-width: 250px; | |
} | |
.toast-container.show-toast { | |
visibility: visible; | |
right: 24px; | |
animation: slidein 0.5s; | |
} | |
.toast-container.hide-toast { | |
visibility: visible; | |
animation: slideout 0.5s; | |
} | |
@keyframes slidein { | |
from { | |
right: -1000px; | |
opacity: 0; | |
} | |
to { | |
right: 24px; | |
opacity: 1; | |
} | |
} | |
@keyframes slideout { | |
from { | |
right: 24px; | |
opacity: 1; | |
} | |
to { | |
right: -1000px; | |
opacity: 0; | |
} | |
} |
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, { useState, useEffect } from "react"; | |
import ReactDOM from "react-dom"; | |
import uuid from "uuid"; | |
import "./styles.css"; | |
const Toast = ({ id, delay = 5500, message, onHide }) => { | |
const [className, setClassname] = useState("toast-container show-toast"); | |
console.log("render toast"); | |
useEffect( | |
() => { | |
console.log("toast set timeout"); | |
let hideTimeout = null; | |
const timeout = setTimeout(() => { | |
console.log("toast timeout"); | |
setClassname("toast-container hide-toast"); | |
console.log("hide toast"); | |
hideTimeout = setTimeout(() => { | |
onHide && onHide(id); | |
}, 500); | |
}, delay); | |
return () => { | |
console.log("toast clear timeout"); | |
clearTimeout(timeout); | |
clearTimeout(hideTimeout); | |
}; | |
}, | |
[id, delay, onHide] | |
); | |
return <div className={className}>{message}</div>; | |
}; | |
const ToastsContainer = ({ toasts, onToastFinished }) => { | |
return ( | |
<div className="toasts-container"> | |
{toasts.map((toast, index) => ( | |
<Toast key={index} {...toast} onHide={onToastFinished} /> | |
))} | |
</div> | |
); | |
}; | |
function App() { | |
const [toasts, setToasts] = useState([]); | |
const showToast = () => { | |
const toast = { | |
id: toasts.length, | |
message: `This is the ${toasts.length + 1} toast message`, | |
delay: 2500 | |
}; | |
setToasts([...toasts, toast].reverse()); | |
}; | |
const onToastFinished = id => { | |
setToasts(toasts.filter(toast => toast.id !== id)); | |
}; | |
return ( | |
<div className="App"> | |
<button onClick={showToast}>Show toast</button> | |
<ToastsContainer toasts={toasts} onToastFinished={onToastFinished} /> | |
</div> | |
); | |
} | |
const rootElement = document.getElementById("root"); | |
ReactDOM.render(<App />, rootElement); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment