fix: SlideToConfirm stale closure — live refs for disabled + onConfirm; horizontal-only drag on iOS
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* SlideToConfirm — pure RN, no RNGH, no Reanimated.
|
||||
* PanResponder on handle + Animated(useNativeDriver:false).
|
||||
*
|
||||
* Fix: live refs break stale closures — disabledRef + onConfirmRef
|
||||
* updated on every render so PanResponder always reads current values.
|
||||
*/
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
@@ -28,17 +31,25 @@ export function SlideToConfirm({ onConfirm, label = 'Slide to confirm', disabled
|
||||
const confirmed = useRef(false);
|
||||
const translateX = useRef(new Animated.Value(0)).current;
|
||||
|
||||
// ── Live refs: break stale closures inside PanResponder ──────────────────
|
||||
const disabledRef = useRef(disabled);
|
||||
disabledRef.current = disabled; // updated on every render
|
||||
const onConfirmRef = useRef(onConfirm);
|
||||
onConfirmRef.current = onConfirm; // updated on every render
|
||||
|
||||
const panResponder = useRef(
|
||||
PanResponder.create({
|
||||
onStartShouldSetPanResponder: () => !disabled,
|
||||
onMoveShouldSetPanResponder: () => !disabled,
|
||||
onStartShouldSetPanResponder: () => !disabledRef.current,
|
||||
// Horizontal-dominance check prevents ScrollView stealing vertical-ish drags on iOS
|
||||
onMoveShouldSetPanResponder: (_, gs) =>
|
||||
!disabledRef.current && Math.abs(gs.dx) > Math.abs(gs.dy) * 2,
|
||||
onPanResponderGrant: () => {
|
||||
confirmed.current = false;
|
||||
(translateX as any).setOffset((translateX as any)._value);
|
||||
translateX.setValue(0);
|
||||
},
|
||||
onPanResponderMove: (_, gs) => {
|
||||
const maxX = Math.max(trackWidth.current - HANDLE_SIZE - 6, 1);
|
||||
const maxX = Math.max(trackWidth.current - HANDLE_SIZE - 6, 1);
|
||||
const clamped = Math.min(Math.max(gs.dx, 0), maxX);
|
||||
translateX.setValue(clamped - (translateX as any)._offset);
|
||||
|
||||
@@ -51,7 +62,7 @@ export function SlideToConfirm({ onConfirm, label = 'Slide to confirm', disabled
|
||||
damping: 18,
|
||||
stiffness: 220,
|
||||
}).start();
|
||||
onConfirm();
|
||||
onConfirmRef.current(); // always calls latest onConfirm
|
||||
}
|
||||
},
|
||||
onPanResponderRelease: () => {
|
||||
|
||||
Reference in New Issue
Block a user