Make a state asynchronously
const [state, setState] = useState("")
const stateAsync = useAsyncState(state)
// ...some async operation
async getLatestData() {
// slow operation
const data = await fetchData()
// rendered happened! get latest rendered state value
const latestValue = await stateAsync()
}
setState("aaa")
Make a value keeping latest
const [state] = useState("")
const stateLatest = useLatest(state)
// ...some unrendered operation
useEffect(() => {
// latest rendered state value
const latestValue = stateLatest.current()
}, [])
Indicate current component is mounted or not.
const isMounted = useMounted()
if (isMounted) {
console.log("We're mounted!")
}
Skip first trigger of useEffect
const [state, setState] = useState("init")
setState("aaa")
...
setState("bbb")
...
setState("ccc")
useMountedEffect(() => {
// in this example, the initial state value "init" will not be printed.
// output:
// state changed: aaa
// state changed: bbb
// state changed: ccc
console.log(`state changed: ${state}`)
}, [state])
use requestAnimationFrame to optimize function
const [windowSize, setWindowSize] = useState(0)
const [setWindowSizeRAF] = useRafCallback((currentWindowSize: number) => {
setWindowSize(currentWindowSize)
})
useEffect(() => {
// resize can be triggered in very high frequency.
// to reduce battery cost, we should use RAF.
const onWindowResize = () => {
setWindowSizeRAF(window.innerHeight)
}
window.addEventListener('resize', onWindowResize)
return () => window.removeEventListener('resize;, onWindowResize)
}, [])
Check user is scrolled to bottom
const isBottom = useScreenBottom()
if (isBottom) {
console.log("we're at the bottom!")
}