@react-aria/interactions 3.15.1 → 3.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/usePress.ts CHANGED
@@ -16,8 +16,8 @@
16
16
  // See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
17
17
 
18
18
  import {disableTextSelection, restoreTextSelection} from './textSelection';
19
- import {DOMAttributes, FocusableElement, PointerType, PressEvents} from '@react-types/shared';
20
- import {focusWithoutScrolling, isVirtualClick, isVirtualPointerEvent, mergeProps, useGlobalListeners, useSyncRef} from '@react-aria/utils';
19
+ import {DOMAttributes, FocusableElement, PressEvent as IPressEvent, PointerType, PressEvents} from '@react-types/shared';
20
+ import {focusWithoutScrolling, isVirtualClick, isVirtualPointerEvent, mergeProps, useEffectEvent, useGlobalListeners, useSyncRef} from '@react-aria/utils';
21
21
  import {PressResponderContext} from './context';
22
22
  import {RefObject, useContext, useEffect, useMemo, useRef, useState} from 'react';
23
23
 
@@ -84,6 +84,35 @@ function usePressResponderContext(props: PressHookProps): PressHookProps {
84
84
  return props;
85
85
  }
86
86
 
87
+ class PressEvent implements IPressEvent {
88
+ type: IPressEvent['type'];
89
+ pointerType: PointerType;
90
+ target: Element;
91
+ shiftKey: boolean;
92
+ ctrlKey: boolean;
93
+ metaKey: boolean;
94
+ altKey: boolean;
95
+ #shouldStopPropagation = true;
96
+
97
+ constructor(type: IPressEvent['type'], pointerType: PointerType, originalEvent: EventBase) {
98
+ this.type = type;
99
+ this.pointerType = pointerType;
100
+ this.target = originalEvent.currentTarget as Element;
101
+ this.shiftKey = originalEvent.shiftKey;
102
+ this.metaKey = originalEvent.metaKey;
103
+ this.ctrlKey = originalEvent.ctrlKey;
104
+ this.altKey = originalEvent.altKey;
105
+ }
106
+
107
+ continuePropagation() {
108
+ this.#shouldStopPropagation = false;
109
+ }
110
+
111
+ get shouldStopPropagation() {
112
+ return this.#shouldStopPropagation;
113
+ }
114
+ }
115
+
87
116
  /**
88
117
  * Handles press interactions across mouse, touch, keyboard, and screen readers.
89
118
  * It normalizes behavior across browsers and platforms, and handles many nuances
@@ -105,8 +134,6 @@ export function usePress(props: PressHookProps): PressResult {
105
134
  ref: _, // Removing `ref` from `domProps` because TypeScript is dumb
106
135
  ...domProps
107
136
  } = usePressResponderContext(props);
108
- let propsRef = useRef<PressHookProps>(null);
109
- propsRef.current = {onPress, onPressChange, onPressStart, onPressEnd, onPressUp, isDisabled, shouldCancelOnPointerExit};
110
137
 
111
138
  let [isPressed, setPressed] = useState(false);
112
139
  let ref = useRef<PressState>({
@@ -122,129 +149,122 @@ export function usePress(props: PressHookProps): PressResult {
122
149
 
123
150
  let {addGlobalListener, removeAllGlobalListeners} = useGlobalListeners();
124
151
 
125
- let pressProps = useMemo(() => {
152
+ let triggerPressStart = useEffectEvent((originalEvent: EventBase, pointerType: PointerType) => {
126
153
  let state = ref.current;
127
- let triggerPressStart = (originalEvent: EventBase, pointerType: PointerType) => {
128
- let {onPressStart, onPressChange, isDisabled} = propsRef.current;
129
- if (isDisabled || state.didFirePressStart) {
130
- return;
131
- }
154
+ if (isDisabled || state.didFirePressStart) {
155
+ return;
156
+ }
132
157
 
133
- if (onPressStart) {
134
- onPressStart({
135
- type: 'pressstart',
136
- pointerType,
137
- target: originalEvent.currentTarget as Element,
138
- shiftKey: originalEvent.shiftKey,
139
- metaKey: originalEvent.metaKey,
140
- ctrlKey: originalEvent.ctrlKey,
141
- altKey: originalEvent.altKey
142
- });
143
- }
158
+ let shouldStopPropagation = true;
159
+ if (onPressStart) {
160
+ let event = new PressEvent('pressstart', pointerType, originalEvent);
161
+ onPressStart(event);
162
+ shouldStopPropagation = event.shouldStopPropagation;
163
+ }
144
164
 
145
- if (onPressChange) {
146
- onPressChange(true);
147
- }
165
+ if (onPressChange) {
166
+ onPressChange(true);
167
+ }
148
168
 
149
- state.didFirePressStart = true;
150
- setPressed(true);
151
- };
169
+ state.didFirePressStart = true;
170
+ setPressed(true);
171
+ return shouldStopPropagation;
172
+ });
152
173
 
153
- let triggerPressEnd = (originalEvent: EventBase, pointerType: PointerType, wasPressed = true) => {
154
- let {onPressEnd, onPressChange, onPress, isDisabled} = propsRef.current;
155
- if (!state.didFirePressStart) {
156
- return;
157
- }
174
+ let triggerPressEnd = useEffectEvent((originalEvent: EventBase, pointerType: PointerType, wasPressed = true) => {
175
+ let state = ref.current;
176
+ if (!state.didFirePressStart) {
177
+ return;
178
+ }
158
179
 
159
- state.ignoreClickAfterPress = true;
160
- state.didFirePressStart = false;
161
-
162
- if (onPressEnd) {
163
- onPressEnd({
164
- type: 'pressend',
165
- pointerType,
166
- target: originalEvent.currentTarget as Element,
167
- shiftKey: originalEvent.shiftKey,
168
- metaKey: originalEvent.metaKey,
169
- ctrlKey: originalEvent.ctrlKey,
170
- altKey: originalEvent.altKey
171
- });
172
- }
180
+ state.ignoreClickAfterPress = true;
181
+ state.didFirePressStart = false;
173
182
 
174
- if (onPressChange) {
175
- onPressChange(false);
176
- }
183
+ let shouldStopPropagation = true;
184
+ if (onPressEnd) {
185
+ let event = new PressEvent('pressend', pointerType, originalEvent);
186
+ onPressEnd(event);
187
+ shouldStopPropagation = event.shouldStopPropagation;
188
+ }
177
189
 
178
- setPressed(false);
179
-
180
- if (onPress && wasPressed && !isDisabled) {
181
- onPress({
182
- type: 'press',
183
- pointerType,
184
- target: originalEvent.currentTarget as Element,
185
- shiftKey: originalEvent.shiftKey,
186
- metaKey: originalEvent.metaKey,
187
- ctrlKey: originalEvent.ctrlKey,
188
- altKey: originalEvent.altKey
189
- });
190
- }
191
- };
190
+ if (onPressChange) {
191
+ onPressChange(false);
192
+ }
192
193
 
193
- let triggerPressUp = (originalEvent: EventBase, pointerType: PointerType) => {
194
- let {onPressUp, isDisabled} = propsRef.current;
195
- if (isDisabled) {
196
- return;
197
- }
194
+ setPressed(false);
198
195
 
199
- if (onPressUp) {
200
- onPressUp({
201
- type: 'pressup',
202
- pointerType,
203
- target: originalEvent.currentTarget as Element,
204
- shiftKey: originalEvent.shiftKey,
205
- metaKey: originalEvent.metaKey,
206
- ctrlKey: originalEvent.ctrlKey,
207
- altKey: originalEvent.altKey
208
- });
209
- }
210
- };
196
+ if (onPress && wasPressed && !isDisabled) {
197
+ let event = new PressEvent('press', pointerType, originalEvent);
198
+ onPress(event);
199
+ shouldStopPropagation &&= event.shouldStopPropagation;
200
+ }
211
201
 
212
- let cancel = (e: EventBase) => {
213
- if (state.isPressed) {
214
- if (state.isOverTarget) {
215
- triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
216
- }
217
- state.isPressed = false;
218
- state.isOverTarget = false;
219
- state.activePointerId = null;
220
- state.pointerType = null;
221
- removeAllGlobalListeners();
222
- if (!allowTextSelectionOnPress) {
223
- restoreTextSelection(state.target);
224
- }
202
+ return shouldStopPropagation;
203
+ });
204
+
205
+ let triggerPressUp = useEffectEvent((originalEvent: EventBase, pointerType: PointerType) => {
206
+ if (isDisabled) {
207
+ return;
208
+ }
209
+
210
+ if (onPressUp) {
211
+ let event = new PressEvent('pressup', pointerType, originalEvent);
212
+ onPressUp(event);
213
+ return event.shouldStopPropagation;
214
+ }
215
+
216
+ return true;
217
+ });
218
+
219
+ let cancel = useEffectEvent((e: EventBase) => {
220
+ let state = ref.current;
221
+ if (state.isPressed) {
222
+ if (state.isOverTarget) {
223
+ triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
225
224
  }
226
- };
225
+ state.isPressed = false;
226
+ state.isOverTarget = false;
227
+ state.activePointerId = null;
228
+ state.pointerType = null;
229
+ removeAllGlobalListeners();
230
+ if (!allowTextSelectionOnPress) {
231
+ restoreTextSelection(state.target);
232
+ }
233
+ }
234
+ });
235
+
236
+ let cancelOnPointerExit = useEffectEvent((e: EventBase) => {
237
+ if (shouldCancelOnPointerExit) {
238
+ cancel(e);
239
+ }
240
+ });
227
241
 
242
+ let pressProps = useMemo(() => {
243
+ let state = ref.current;
228
244
  let pressProps: DOMAttributes = {
229
245
  onKeyDown(e) {
230
246
  if (isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && e.currentTarget.contains(e.target as Element)) {
231
247
  if (shouldPreventDefaultKeyboard(e.target as Element, e.key)) {
232
248
  e.preventDefault();
233
249
  }
234
- e.stopPropagation();
235
250
 
236
251
  // If the event is repeating, it may have started on a different element
237
252
  // after which focus moved to the current element. Ignore these events and
238
253
  // only handle the first key down event.
254
+ let shouldStopPropagation = true;
239
255
  if (!state.isPressed && !e.repeat) {
240
256
  state.target = e.currentTarget;
241
257
  state.isPressed = true;
242
- triggerPressStart(e, 'keyboard');
258
+ shouldStopPropagation = triggerPressStart(e, 'keyboard');
243
259
 
244
260
  // Focus may move before the key up event, so register the event on the document
245
261
  // instead of the same element where the key down event occurred.
246
262
  addGlobalListener(document, 'keyup', onKeyUp, false);
247
263
  }
264
+
265
+ if (shouldStopPropagation) {
266
+ e.stopPropagation();
267
+ }
248
268
  } else if (e.key === 'Enter' && isHTMLAnchorLink(e.currentTarget)) {
249
269
  // If the target is a link, we won't have handled this above because we want the default
250
270
  // browser behavior to open the link when pressing Enter. But we still need to prevent
@@ -263,7 +283,7 @@ export function usePress(props: PressHookProps): PressResult {
263
283
  }
264
284
 
265
285
  if (e && e.button === 0) {
266
- e.stopPropagation();
286
+ let shouldStopPropagation = true;
267
287
  if (isDisabled) {
268
288
  e.preventDefault();
269
289
  }
@@ -276,13 +296,17 @@ export function usePress(props: PressHookProps): PressResult {
276
296
  focusWithoutScrolling(e.currentTarget);
277
297
  }
278
298
 
279
- triggerPressStart(e, 'virtual');
280
- triggerPressUp(e, 'virtual');
281
- triggerPressEnd(e, 'virtual');
299
+ let stopPressStart = triggerPressStart(e, 'virtual');
300
+ let stopPressUp = triggerPressUp(e, 'virtual');
301
+ let stopPressEnd = triggerPressEnd(e, 'virtual');
302
+ shouldStopPropagation = stopPressStart && stopPressUp && stopPressEnd;
282
303
  }
283
304
 
284
305
  state.ignoreEmulatedMouseEvents = false;
285
306
  state.ignoreClickAfterPress = false;
307
+ if (shouldStopPropagation) {
308
+ e.stopPropagation();
309
+ }
286
310
  }
287
311
  }
288
312
  };
@@ -292,13 +316,16 @@ export function usePress(props: PressHookProps): PressResult {
292
316
  if (shouldPreventDefaultKeyboard(e.target as Element, e.key)) {
293
317
  e.preventDefault();
294
318
  }
295
- e.stopPropagation();
296
319
 
297
320
  state.isPressed = false;
298
321
  let target = e.target as Element;
299
- triggerPressEnd(createEvent(state.target, e), 'keyboard', state.target.contains(target));
322
+ let shouldStopPropagation = triggerPressEnd(createEvent(state.target, e), 'keyboard', state.target.contains(target));
300
323
  removeAllGlobalListeners();
301
324
 
325
+ if (shouldStopPropagation) {
326
+ e.stopPropagation();
327
+ }
328
+
302
329
  // If the target is a link, trigger the click method to open the URL,
303
330
  // but defer triggering pressEnd until onClick event handler.
304
331
  if (state.target instanceof HTMLElement && state.target.contains(target) && (isHTMLAnchorLink(state.target) || state.target.getAttribute('role') === 'link')) {
@@ -331,7 +358,7 @@ export function usePress(props: PressHookProps): PressResult {
331
358
 
332
359
  state.pointerType = e.pointerType;
333
360
 
334
- e.stopPropagation();
361
+ let shouldStopPropagation = true;
335
362
  if (!state.isPressed) {
336
363
  state.isPressed = true;
337
364
  state.isOverTarget = true;
@@ -346,12 +373,16 @@ export function usePress(props: PressHookProps): PressResult {
346
373
  disableTextSelection(state.target);
347
374
  }
348
375
 
349
- triggerPressStart(e, state.pointerType);
376
+ shouldStopPropagation = triggerPressStart(e, state.pointerType);
350
377
 
351
378
  addGlobalListener(document, 'pointermove', onPointerMove, false);
352
379
  addGlobalListener(document, 'pointerup', onPointerUp, false);
353
380
  addGlobalListener(document, 'pointercancel', onPointerCancel, false);
354
381
  }
382
+
383
+ if (shouldStopPropagation) {
384
+ e.stopPropagation();
385
+ }
355
386
  };
356
387
 
357
388
  pressProps.onMouseDown = (e) => {
@@ -401,9 +432,7 @@ export function usePress(props: PressHookProps): PressResult {
401
432
  } else if (state.isOverTarget) {
402
433
  state.isOverTarget = false;
403
434
  triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
404
- if (propsRef.current.shouldCancelOnPointerExit) {
405
- cancel(e);
406
- }
435
+ cancelOnPointerExit(e);
407
436
  }
408
437
  };
409
438
 
@@ -451,8 +480,8 @@ export function usePress(props: PressHookProps): PressResult {
451
480
  e.preventDefault();
452
481
  }
453
482
 
454
- e.stopPropagation();
455
483
  if (state.ignoreEmulatedMouseEvents) {
484
+ e.stopPropagation();
456
485
  return;
457
486
  }
458
487
 
@@ -465,7 +494,10 @@ export function usePress(props: PressHookProps): PressResult {
465
494
  focusWithoutScrolling(e.currentTarget);
466
495
  }
467
496
 
468
- triggerPressStart(e, state.pointerType);
497
+ let shouldStopPropagation = triggerPressStart(e, state.pointerType);
498
+ if (shouldStopPropagation) {
499
+ e.stopPropagation();
500
+ }
469
501
 
470
502
  addGlobalListener(document, 'mouseup', onMouseUp, false);
471
503
  };
@@ -475,10 +507,14 @@ export function usePress(props: PressHookProps): PressResult {
475
507
  return;
476
508
  }
477
509
 
478
- e.stopPropagation();
510
+ let shouldStopPropagation = true;
479
511
  if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
480
512
  state.isOverTarget = true;
481
- triggerPressStart(e, state.pointerType);
513
+ shouldStopPropagation = triggerPressStart(e, state.pointerType);
514
+ }
515
+
516
+ if (shouldStopPropagation) {
517
+ e.stopPropagation();
482
518
  }
483
519
  };
484
520
 
@@ -487,13 +523,15 @@ export function usePress(props: PressHookProps): PressResult {
487
523
  return;
488
524
  }
489
525
 
490
- e.stopPropagation();
526
+ let shouldStopPropagation = true;
491
527
  if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
492
528
  state.isOverTarget = false;
493
- triggerPressEnd(e, state.pointerType, false);
494
- if (propsRef.current.shouldCancelOnPointerExit) {
495
- cancel(e);
496
- }
529
+ shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
530
+ cancelOnPointerExit(e);
531
+ }
532
+
533
+ if (shouldStopPropagation) {
534
+ e.stopPropagation();
497
535
  }
498
536
  };
499
537
 
@@ -535,7 +573,6 @@ export function usePress(props: PressHookProps): PressResult {
535
573
  return;
536
574
  }
537
575
 
538
- e.stopPropagation();
539
576
  let touch = getTouchFromEvent(e.nativeEvent);
540
577
  if (!touch) {
541
578
  return;
@@ -557,7 +594,10 @@ export function usePress(props: PressHookProps): PressResult {
557
594
  disableTextSelection(state.target);
558
595
  }
559
596
 
560
- triggerPressStart(e, state.pointerType);
597
+ let shouldStopPropagation = triggerPressStart(e, state.pointerType);
598
+ if (shouldStopPropagation) {
599
+ e.stopPropagation();
600
+ }
561
601
 
562
602
  addGlobalListener(window, 'scroll', onScroll, true);
563
603
  };
@@ -567,23 +607,26 @@ export function usePress(props: PressHookProps): PressResult {
567
607
  return;
568
608
  }
569
609
 
570
- e.stopPropagation();
571
610
  if (!state.isPressed) {
611
+ e.stopPropagation();
572
612
  return;
573
613
  }
574
614
 
575
615
  let touch = getTouchById(e.nativeEvent, state.activePointerId);
616
+ let shouldStopPropagation = true;
576
617
  if (touch && isOverTarget(touch, e.currentTarget)) {
577
618
  if (!state.isOverTarget) {
578
619
  state.isOverTarget = true;
579
- triggerPressStart(e, state.pointerType);
620
+ shouldStopPropagation = triggerPressStart(e, state.pointerType);
580
621
  }
581
622
  } else if (state.isOverTarget) {
582
623
  state.isOverTarget = false;
583
- triggerPressEnd(e, state.pointerType, false);
584
- if (propsRef.current.shouldCancelOnPointerExit) {
585
- cancel(e);
586
- }
624
+ shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
625
+ cancelOnPointerExit(e);
626
+ }
627
+
628
+ if (shouldStopPropagation) {
629
+ e.stopPropagation();
587
630
  }
588
631
  };
589
632
 
@@ -592,17 +635,22 @@ export function usePress(props: PressHookProps): PressResult {
592
635
  return;
593
636
  }
594
637
 
595
- e.stopPropagation();
596
638
  if (!state.isPressed) {
639
+ e.stopPropagation();
597
640
  return;
598
641
  }
599
642
 
600
643
  let touch = getTouchById(e.nativeEvent, state.activePointerId);
644
+ let shouldStopPropagation = true;
601
645
  if (touch && isOverTarget(touch, e.currentTarget)) {
602
646
  triggerPressUp(e, state.pointerType);
603
- triggerPressEnd(e, state.pointerType);
647
+ shouldStopPropagation = triggerPressEnd(e, state.pointerType);
604
648
  } else if (state.isOverTarget) {
605
- triggerPressEnd(e, state.pointerType, false);
649
+ shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
650
+ }
651
+
652
+ if (shouldStopPropagation) {
653
+ e.stopPropagation();
606
654
  }
607
655
 
608
656
  state.isPressed = false;
@@ -648,7 +696,18 @@ export function usePress(props: PressHookProps): PressResult {
648
696
  }
649
697
 
650
698
  return pressProps;
651
- }, [addGlobalListener, isDisabled, preventFocusOnPress, removeAllGlobalListeners, allowTextSelectionOnPress]);
699
+ }, [
700
+ addGlobalListener,
701
+ isDisabled,
702
+ preventFocusOnPress,
703
+ removeAllGlobalListeners,
704
+ allowTextSelectionOnPress,
705
+ cancel,
706
+ cancelOnPointerExit,
707
+ triggerPressEnd,
708
+ triggerPressStart,
709
+ triggerPressUp
710
+ ]);
652
711
 
653
712
  // Remove user-select: none in case component unmounts immediately after pressStart
654
713
  // eslint-disable-next-line arrow-body-style
@@ -779,7 +838,7 @@ function shouldPreventDefaultKeyboard(target: Element, key: string) {
779
838
  }
780
839
 
781
840
  if (target instanceof HTMLButtonElement) {
782
- return target.type !== 'submit';
841
+ return target.type !== 'submit' && target.type !== 'reset';
783
842
  }
784
843
 
785
844
  return true;
package/src/utils.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import {FocusEvent as ReactFocusEvent, useCallback, useRef} from 'react';
14
- import {useLayoutEffect} from '@react-aria/utils';
14
+ import {useEffectEvent, useLayoutEffect} from '@react-aria/utils';
15
15
 
16
16
  export class SyntheticFocusEvent<Target = Element> implements ReactFocusEvent<Target> {
17
17
  nativeEvent: FocusEvent;
@@ -64,10 +64,8 @@ export class SyntheticFocusEvent<Target = Element> implements ReactFocusEvent<Ta
64
64
  export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEvent<Target>) => void) {
65
65
  let stateRef = useRef({
66
66
  isFocused: false,
67
- onBlur,
68
67
  observer: null as MutationObserver
69
68
  });
70
- stateRef.current.onBlur = onBlur;
71
69
 
72
70
  // Clean up MutationObserver on unmount. See below.
73
71
  // eslint-disable-next-line arrow-body-style
@@ -81,6 +79,10 @@ export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEv
81
79
  };
82
80
  }, []);
83
81
 
82
+ let dispatchBlur = useEffectEvent((e: SyntheticFocusEvent<Target>) => {
83
+ onBlur?.(e);
84
+ });
85
+
84
86
  // This function is called during a React onFocus event.
85
87
  return useCallback((e: ReactFocusEvent<Target>) => {
86
88
  // React does not fire onBlur when an element is disabled. https://github.com/facebook/react/issues/9142
@@ -101,7 +103,7 @@ export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEv
101
103
 
102
104
  if (target.disabled) {
103
105
  // For backward compatibility, dispatch a (fake) React synthetic event.
104
- stateRef.current.onBlur?.(new SyntheticFocusEvent('blur', e));
106
+ dispatchBlur(new SyntheticFocusEvent('blur', e));
105
107
  }
106
108
 
107
109
  // We no longer need the MutationObserver once the target is blurred.
@@ -116,12 +118,13 @@ export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEv
116
118
  stateRef.current.observer = new MutationObserver(() => {
117
119
  if (stateRef.current.isFocused && target.disabled) {
118
120
  stateRef.current.observer.disconnect();
119
- target.dispatchEvent(new FocusEvent('blur'));
120
- target.dispatchEvent(new FocusEvent('focusout', {bubbles: true}));
121
+ let relatedTargetEl = target === document.activeElement ? null : document.activeElement;
122
+ target.dispatchEvent(new FocusEvent('blur', {relatedTarget: relatedTargetEl}));
123
+ target.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: relatedTargetEl}));
121
124
  }
122
125
  });
123
126
 
124
127
  stateRef.current.observer.observe(target, {attributes: true, attributeFilter: ['disabled']});
125
128
  }
126
- }, []);
129
+ }, [dispatchBlur]);
127
130
  }