Skip to content

Commit f0458fb

Browse files
authored
feat(ui): use native useEffectEvent if available (#15304)
React has officially added support for `useEffectEvent` in 19.2.0. This PR makes our `useEffectEvent` an alias for React's native `useEffectEvent` if it's available. If it's not available, it will use our existing polyfill.
1 parent 12b679f commit f0458fb

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

packages/ui/src/hooks/useEffectEvent.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/**
44
5-
Taken and modified from https://github.com/bluesky-social/social-app/blob/ce0bf867ff3b50a495d8db242a7f55371bffeadc/src/lib/hooks/useNonReactiveCallback.ts
5+
Polyfill taken and modified from https://github.com/bluesky-social/social-app/blob/ce0bf867ff3b50a495d8db242a7f55371bffeadc/src/lib/hooks/useNonReactiveCallback.ts
66
77
Copyright 2023–2025 Bluesky PBC
88
@@ -13,7 +13,7 @@ The above copyright notice and this permission notice shall be included in all c
1313
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1414
*/
1515

16-
import { useCallback, useInsertionEffect, useRef } from 'react'
16+
import React, { useCallback, useInsertionEffect, useRef } from 'react'
1717

1818
// This should be used sparingly. It erases reactivity, i.e. when the inputs
1919
// change, the function itself will remain the same. This means that if you
@@ -23,14 +23,20 @@ import { useCallback, useInsertionEffect, useRef } from 'react'
2323
//
2424
// Also, you should avoid calling the returned function during rendering
2525
// since the values captured by it are going to lag behind.
26-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
27-
export function useEffectEvent<T extends Function>(fn: T): T {
28-
const ref = useRef(fn)
29-
useInsertionEffect(() => {
30-
ref.current = fn
31-
}, [fn])
32-
return useCallback((...args: any) => {
33-
const latestFn = ref.current
34-
return latestFn(...args)
35-
}, []) as unknown as T
36-
}
26+
27+
export const useEffectEvent =
28+
'useEffectEvent' in React && typeof React.useEffectEvent === 'function'
29+
? // useEffectEvent is available in Next.js 16 / newer versions of React
30+
React.useEffectEvent
31+
: // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
32+
<T extends Function>(fn: T): T => {
33+
// useEffectEvent is not available in older versions of React, so we need to polyfill it
34+
const ref = useRef(fn)
35+
useInsertionEffect(() => {
36+
ref.current = fn
37+
}, [fn])
38+
return useCallback((...args: any) => {
39+
const latestFn = ref.current
40+
return latestFn(...args)
41+
}, []) as unknown as T
42+
}

0 commit comments

Comments
 (0)