1
1
import { Suggest2 , Suggest2Props } from '@blueprintjs/select'
2
2
3
- import { noop } from 'lodash-es'
3
+ import { debounce , noop } from 'lodash-es'
4
4
import { useEffect , useMemo , useRef , useState } from 'react'
5
5
import { ControllerFieldState } from 'react-hook-form'
6
6
7
7
import { FieldResetButton } from './FieldResetButton'
8
8
9
9
interface SuggestProps < T > extends Suggest2Props < T > {
10
- debounce ?: number // defaults to 100(ms), set to 0 to disable
10
+ query ?: string // controlled query, optional
11
+ debounce ?: number // defaults to 100(ms)
11
12
updateQueryOnSelect ?: boolean
12
13
fieldState ?: ControllerFieldState
14
+ onDebouncedQueryChange ?: ( query : string ) => void
13
15
onReset ?: ( ) => void
14
16
}
15
17
16
18
export const Suggest = < T , > ( {
17
- debounce = 100 ,
19
+ debounce : debounceTime = 100 ,
18
20
updateQueryOnSelect,
19
21
fieldState,
22
+ query : propQuery ,
23
+ onQueryChange,
24
+ onDebouncedQueryChange,
20
25
onReset,
21
26
22
- items,
23
27
itemListPredicate,
24
28
selectedItem,
25
29
inputValueRenderer,
@@ -33,45 +37,60 @@ export const Suggest = <T,>({
33
37
ref . current [ 'selectText' ] = noop
34
38
}
35
39
36
- const [ query , setQuery ] = useState ( '' )
40
+ const onQueryChangeRef = useRef ( onQueryChange )
41
+ onQueryChangeRef . current = onQueryChange
42
+ const onDebouncedQueryChangeRef = useRef ( onDebouncedQueryChange )
43
+ onDebouncedQueryChangeRef . current = onDebouncedQueryChange
44
+
45
+ const [ internalQuery , setInternalQuery ] = useState ( '' )
37
46
const [ debouncedQuery , setDebouncedQuery ] = useState ( '' )
47
+ const query = propQuery ?? internalQuery
48
+ const updateQuery = useMemo ( ( ) => {
49
+ // note: debouncing is required to fix https://github.com/MaaAssistantArknights/maa-copilot-frontend/issues/72
50
+ const debouncedUpdateQuery = debounce ( ( query : string ) => {
51
+ setDebouncedQuery ( query )
52
+ onDebouncedQueryChangeRef . current ?.( query )
53
+ } , debounceTime )
38
54
39
- // the debounce fixes https://github.com/MaaAssistantArknights/maa-copilot-frontend/issues/72
40
- useEffect ( ( ) => {
41
- if ( debounce ) {
42
- const timer = setTimeout ( ( ) => setDebouncedQuery ( query ) , debounce )
43
- return ( ) => clearTimeout ( timer )
55
+ const updateQuery = ( query : string , immediately : boolean ) => {
56
+ setInternalQuery ( query )
57
+ onQueryChangeRef . current ?.( query )
58
+ debouncedUpdateQuery ( query )
59
+ if ( immediately ) {
60
+ debouncedUpdateQuery . flush ( )
61
+ }
44
62
}
45
- setDebouncedQuery ( query )
46
- return undefined
47
- } , [ query , debounce ] )
63
+ updateQuery . cancel = debouncedUpdateQuery . cancel
64
+ return updateQuery
65
+ } , [ debounceTime ] )
48
66
49
- const filteredItems = useMemo (
50
- ( ) => itemListPredicate ?.( debouncedQuery , items ) || items ,
51
- [ itemListPredicate , debouncedQuery , items ] ,
52
- )
67
+ // 取消等待中的调用
68
+ useEffect ( ( ) => ( ) => updateQuery . cancel ( ) , [ updateQuery ] )
53
69
54
70
useEffect ( ( ) => {
55
- if ( ! fieldState ?. isTouched ) {
56
- setQuery ( '' )
57
- setDebouncedQuery ( '' )
71
+ if ( fieldState && ! fieldState . isTouched ) {
72
+ updateQuery ( '' , true )
58
73
}
59
- } , [ fieldState ?. isTouched ] )
74
+ } , [ fieldState , updateQuery ] )
60
75
61
76
useEffect ( ( ) => {
62
77
if ( updateQueryOnSelect && selectedItem ) {
63
- setQuery ( inputValueRenderer ( selectedItem ) )
78
+ updateQuery ( inputValueRenderer ( selectedItem ) , true )
64
79
}
65
- } , [ updateQueryOnSelect , selectedItem , inputValueRenderer ] )
80
+ } , [ updateQueryOnSelect , selectedItem , inputValueRenderer , updateQuery ] )
66
81
67
82
return (
68
83
< Suggest2 < T >
69
84
ref = { ref }
70
- items = { filteredItems }
71
85
query = { query }
72
- onQueryChange = { setQuery }
86
+ onQueryChange = { ( query ) => updateQuery ( query , false ) }
73
87
selectedItem = { selectedItem }
74
88
inputValueRenderer = { inputValueRenderer }
89
+ itemListPredicate = {
90
+ itemListPredicate
91
+ ? ( query , items ) => itemListPredicate ( debouncedQuery , items )
92
+ : undefined
93
+ }
75
94
inputProps = { {
76
95
onKeyDown : ( event ) => {
77
96
// prevent form submission
@@ -82,15 +101,17 @@ export const Suggest = <T,>({
82
101
rightElement : (
83
102
< FieldResetButton
84
103
disabled = {
85
- fieldState
86
- ? ! fieldState . isDirty
87
- : onReset
88
- ? ! ( query || selectedItem !== null )
89
- : true
104
+ ! (
105
+ // enabled =
106
+ ( fieldState
107
+ ? fieldState . isDirty
108
+ : onReset
109
+ ? query || selectedItem !== null
110
+ : false )
111
+ )
90
112
}
91
113
onReset = { ( ) => {
92
- setQuery ( '' )
93
- setDebouncedQuery ( '' )
114
+ updateQuery ( '' , true )
94
115
onReset ?.( )
95
116
} }
96
117
/>
0 commit comments