1
1
import 'client-only' ;
2
- import { useCallback , useRef } from 'react' ;
2
+ import { useCallback } from 'react' ;
3
+ import { useSingleton } from '../use-singleton' ;
3
4
4
5
export type UseCompositionInputCallback = ( value : string ) => void ;
5
6
export type UseCompositionInputReturnKey = 'onChange' | 'onCompositionStart' | 'onCompositionEnd' ;
6
7
export type UseCompositionInputReturn = Pick < JSX . IntrinsicElements [ 'input' ] , UseCompositionInputReturnKey > ;
7
8
8
9
/** @see https://foxact.skk.moe/use-composition-input */
9
10
export const useCompositionInput = ( cb : UseCompositionInputCallback ) : UseCompositionInputReturn => {
10
- // @ts -expect-error -- We are using singleton approach here, to prevent repeated initialization.
11
- const internalState : React . MutableRefObject < {
12
- /** is"C"ompositioning */ c : boolean ,
13
- /** is"E"mitted */ e : boolean
14
- } > = useRef ( ) ;
15
-
16
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- it will be undefined only on first render
17
- if ( ! internalState . current ) {
18
- internalState . current = {
19
- /** is"C"ompositioning */ c : false ,
20
- /** is"E"mitted */ e : false
21
- } ;
22
- }
11
+ const internalState = useSingleton ( ( ) => ( {
12
+ /** is"C"ompositioning */ c : false ,
13
+ /** is"E"mitted */ e : false
14
+ } ) ) ;
23
15
24
16
const onChange = useCallback ( ( e : React . ChangeEvent < HTMLInputElement > | React . CompositionEvent < HTMLInputElement > ) => {
25
17
if ( 'value' in e . target ) {
@@ -32,12 +24,12 @@ export const useCompositionInput = (cb: UseCompositionInputCallback): UseComposi
32
24
internalState . current . e = false ;
33
25
}
34
26
}
35
- } , [ cb ] ) ;
27
+ } , [ cb , internalState ] ) ;
36
28
37
29
const onCompositionStart = useCallback < React . CompositionEventHandler < HTMLInputElement > > ( ( ) => {
38
30
internalState . current . c = true ;
39
31
internalState . current . e = false ;
40
- } , [ ] ) ;
32
+ } , [ internalState ] ) ;
41
33
42
34
const onCompositionEnd = useCallback < React . CompositionEventHandler < HTMLInputElement > > ( ( e ) => {
43
35
internalState . current . c = false ;
@@ -48,7 +40,7 @@ export const useCompositionInput = (cb: UseCompositionInputCallback): UseComposi
48
40
if ( ! internalState . current . e ) {
49
41
onChange ( e ) ;
50
42
}
51
- } , [ onChange ] ) ;
43
+ } , [ internalState , onChange ] ) ;
52
44
53
45
return {
54
46
onChange,
0 commit comments