fix: SlideToConfirm stale closure — live refs for disabled + onConfirm; horizontal-only drag on iOS
This commit is contained in:
@@ -9,7 +9,6 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|||||||
import * as Location from 'expo-location';
|
import * as Location from 'expo-location';
|
||||||
import { api } from '../../../services/api';
|
import { api } from '../../../services/api';
|
||||||
import { useAuthStore } from '../../../stores/authStore';
|
import { useAuthStore } from '../../../stores/authStore';
|
||||||
import { SlideToConfirm } from '../../../components/SlideToConfirm';
|
|
||||||
|
|
||||||
// ─── Constants ────────────────────────────────────────────────────────────────
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
||||||
const STATUS_FLOW = ['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'] as const;
|
const STATUS_FLOW = ['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'] as const;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* SlideToConfirm — pure RN, no RNGH, no Reanimated.
|
* SlideToConfirm — pure RN, no RNGH, no Reanimated.
|
||||||
* PanResponder on handle + Animated(useNativeDriver:false).
|
* 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 { useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
@@ -28,10 +31,18 @@ export function SlideToConfirm({ onConfirm, label = 'Slide to confirm', disabled
|
|||||||
const confirmed = useRef(false);
|
const confirmed = useRef(false);
|
||||||
const translateX = useRef(new Animated.Value(0)).current;
|
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(
|
const panResponder = useRef(
|
||||||
PanResponder.create({
|
PanResponder.create({
|
||||||
onStartShouldSetPanResponder: () => !disabled,
|
onStartShouldSetPanResponder: () => !disabledRef.current,
|
||||||
onMoveShouldSetPanResponder: () => !disabled,
|
// 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: () => {
|
onPanResponderGrant: () => {
|
||||||
confirmed.current = false;
|
confirmed.current = false;
|
||||||
(translateX as any).setOffset((translateX as any)._value);
|
(translateX as any).setOffset((translateX as any)._value);
|
||||||
@@ -51,7 +62,7 @@ export function SlideToConfirm({ onConfirm, label = 'Slide to confirm', disabled
|
|||||||
damping: 18,
|
damping: 18,
|
||||||
stiffness: 220,
|
stiffness: 220,
|
||||||
}).start();
|
}).start();
|
||||||
onConfirm();
|
onConfirmRef.current(); // always calls latest onConfirm
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPanResponderRelease: () => {
|
onPanResponderRelease: () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user