Closed ssi02014 closed 3 weeks ago
Latest commit: 4cb88a46d9b3c437e8de2b5cfe3f744422c90d95
The changes in this PR will be included in the next version bump.
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
The latest updates on your projects. Learn more about Vercel for Git ↗︎
Name | Status | Preview | Comments | Updated (UTC) |
---|---|---|---|---|
suspensive.org | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Jun 24, 2024 9:35am |
v1.suspensive.org | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Jun 24, 2024 9:35am |
visualization.suspensive.org | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Jun 24, 2024 9:35am |
Comparing ssi02014:feat/usePreservedCallback
(4cb88a4) with main
(ec57398)
:warning: No benchmarks were detected in both the base of the PR and the PR.
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 80.88%. Comparing base (
ec57398
) to head (4cb88a4
).
@manudeli
To make how to work be same between AS-IS and TO-BE, we should add useCallback in all components using useTimeout. There is no significant difference in components that use useTimeout, but it can be expected that performance will be slightly worse. So I'm confuse that this is really improvement. I need more reasons to merge this change
I did this because what was already written wasn't working as intended 🤔
If you don't want to guarantee latest function
, the code below should be removed because it's pointless.
import { useEffect, useRef } from 'react'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
export const useTimeout = (fn: () => void, ms: number) => {
- const fnRef = useRef(fn)
- useIsomorphicLayoutEffect(() => {
- fnRef.current = fn
- }, [fn])
useEffect(() => {
- const id = setTimeout(fnRef.current, ms)
+ const id = setTimeout(fn, ms)
return () => clearTimeout(id)
}, [ms])
}
++ Even if you don't use usePreservedCallback
and want to guarantee that your function is up-to-date
, you shouldn't put "fn"
in the dependency array of useEffect
because there is an infinite call issue
.
export const usePreservedCallback = <T extends (...args: unknown[]) => unknown>(callback: T) => {
const callbackRef = useRef<T>(callback)
useIsomorphicLayoutEffect(() => {
callbackRef.current = callback
}, [callback])
return callbackRef.current // (*)
}
++ If you return ref.current
directly without using useCallback
as above, this is also problematic because it doesn't return the latest function
.
@manudeli I recently took a deep dive into the usePreservedCallback
hook.
As a result of this reflection, I'm happy to contribute to a great library once again. 🤗🚀
Overview
@manudeli Hello! 👋
Currently,
useTimeout
hook is written to call the changed function when the callback function changes. However, in practice, we're not actually calling the changed function, even if the function changes in the middle.This is because the only value we currently depend on for
useEffect
isms
. Addingref
to the dependency array doesn't solve this problem because it's not tracked.These problems can be solved by using hooks like
usePreservedCallback
intoss/slash
, which can preserve the reference of the callback function, while at the same time ensuring the function is up-to-date.Since the
ref
keeps updating during its lifecycle, when calling the function returned byuseCallback
, the latest function will be called by theclosure
.PR Checklist