@@ -78,9 +78,18 @@ const useSyncInput = (p: UseSyncInputProps) => {
7878 setFilter ( '' )
7979 } , [ setActive , setFilter ] )
8080
81+ // activeRef always holds the latest value of active so the debounced checkTrigger
82+ // timeout reads the current state rather than a stale closure. Without this, rapid
83+ // typing after a slash command can cancel the checkTrigger that would reset active,
84+ // leaving active='commands' when the timeout finally fires over new text.
85+ const activeRef = React . useRef ( active )
86+ React . useLayoutEffect ( ( ) => {
87+ activeRef . current = active
88+ } , [ active ] )
89+
8190 const getWordAtCursor = React . useCallback ( ( ) => {
8291 if ( inputRef . current ) {
83- const useSpaces = active === 'commands'
92+ const useSpaces = activeRef . current === 'commands'
8493 const input = inputRef . current
8594 const selection = input . getSelection ( )
8695 const text = lastTextRef . current
@@ -114,7 +123,7 @@ const useSyncInput = (p: UseSyncInputProps) => {
114123 return { position, word}
115124 }
116125 return null
117- } , [ inputRef , active , lastTextRef ] )
126+ } , [ inputRef , activeRef , lastTextRef ] )
118127
119128 const triggerIDRef = React . useRef < NodeJS . Timeout > ( undefined )
120129 const checkTrigger = React . useCallback ( ( ) => {
@@ -134,8 +143,8 @@ const useSyncInput = (p: UseSyncInputProps) => {
134143 setInactive ( )
135144 return
136145 }
137- if ( active ) {
138- const activeMarker = suggestorToMarker [ active ]
146+ if ( activeRef . current ) {
147+ const activeMarker = suggestorToMarker [ activeRef . current ]
139148 const matchInfo = matchesMarker ( word , activeMarker )
140149 if ( ! matchInfo . matches ) {
141150 // not active anymore
@@ -155,7 +164,7 @@ const useSyncInput = (p: UseSyncInputProps) => {
155164 }
156165 }
157166 } , 1 )
158- } , [ getWordAtCursor , triggerIDRef , setActive , setFilter , setInactive , active , inputRef ] )
167+ } , [ getWordAtCursor , triggerIDRef , setActive , setFilter , setInactive , activeRef , inputRef ] )
159168
160169 React . useEffect ( ( ) => {
161170 return ( ) => {
@@ -165,6 +174,7 @@ const useSyncInput = (p: UseSyncInputProps) => {
165174
166175 const triggerTransform = React . useCallback (
167176 function ( maybeValue : SelectedType | undefined , final = true ) {
177+ const active = activeRef . current
168178 if ( ! inputRef . current || ! active ) {
169179 return
170180 }
@@ -208,7 +218,7 @@ const useSyncInput = (p: UseSyncInputProps) => {
208218 setLastText ( transformedText . text )
209219 input . transformText ( ( ) => transformedText , final )
210220 } ,
211- [ active , inputRef , getWordAtCursor , selectedItemRef , setLastText , lastTextRef ]
221+ [ activeRef , inputRef , getWordAtCursor , selectedItemRef , setLastText , lastTextRef ]
212222 )
213223
214224 return {
0 commit comments