Last active
March 3, 2023 14:46
-
-
Save cfj/c566f645ab3b2efb0a9fc0919847f689 to your computer and use it in GitHub Desktop.
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 { useState, useRef } from 'react'; | |
import styles from '../styles/DebouncedInputFetchDemo.module.css'; | |
const lookupOrder = async (orderNumber, fetchOptions = {}) => { | |
const response = await fetch(`/api/demo?orderNo=${orderNumber}&delay=3`, { | |
method: 'GET', | |
...fetchOptions | |
}); | |
return response.json(); | |
}; | |
const DebouncedInputFetchDemo = () => { | |
const debounceDelay = 750; | |
const debounceTimer = useRef(0); | |
const controller = useRef(); | |
const [loading, setLoading] = useState(false); | |
const [orderNumber, setOrderNumber] = useState(''); | |
const [order, setOrder] = useState(); | |
const performanceEntries = | |
typeof window !== 'undefined' && | |
window.performance && | |
window.performance.getEntries().filter((e) => e.initiatorType === 'fetch' && e.name.includes('demo')); | |
const debouncedFetch = (orderNumber) => { | |
setOrderNumber(orderNumber); | |
clearTimeout(debounceTimer.current); | |
controller.current?.abort(); | |
controller.current = new AbortController(); | |
debounceTimer.current = setTimeout(async () => { | |
setOrder(undefined); | |
try { | |
if (orderNumber) { | |
setLoading(true); | |
const order = await lookupOrder(orderNumber, { | |
signal: controller.current.signal | |
}); | |
setOrder(order); | |
} | |
} catch (err) { | |
if (err instanceof Error && err.name !== 'AbortError') { | |
setError(err); | |
} | |
} finally { | |
setLoading(false); | |
} | |
}, debounceDelay); | |
}; | |
return ( | |
<div className={styles.debouncedForm}> | |
<form> | |
<label htmlFor="order-no">Order number</label> | |
<input | |
autoComplete="off" | |
type="text" | |
id="order-no" | |
className={loading ? styles.loading : order ? styles.success : ''} | |
value={orderNumber} | |
onChange={(e) => debouncedFetch(e.target.value)} | |
/> | |
{order ? <span className="text-green-500 ml-2">Order found: {order.order}</span> : null} | |
</form> | |
{(performanceEntries && performanceEntries.length) || loading ? ( | |
<> | |
<h2>Requests</h2> | |
<div> | |
<ul> | |
{performanceEntries.map((entry, i) => ( | |
<li key={i}> | |
{entry.connectEnd ? ( | |
<span className="text-green-500">200 OK</span> | |
) : ( | |
<span className="text-red-400">Cancelled by AbortController</span> | |
)} | |
</li> | |
))} | |
{loading ? ( | |
<li> | |
<span className="text-yellow-500">Pending...</span> | |
</li> | |
) : null} | |
</ul> | |
</div> | |
</> | |
) : null} | |
</div> | |
); | |
}; | |
export default DebouncedInputFetchDemo; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment