fix(P4A): ImageAnnotator effect-race — stabilize onCancel via ref so URL.revoke doesn't fire mid-decode
This commit is contained in:
@@ -41,6 +41,15 @@ export function ImageAnnotator({ file, onCancel, onSave }: Props) {
|
|||||||
const draftRef = useRef<AnnotatorOp | null>(null);
|
const draftRef = useRef<AnnotatorOp | null>(null);
|
||||||
const [draftTick, setDraftTick] = useState(0);
|
const [draftTick, setDraftTick] = useState(0);
|
||||||
|
|
||||||
|
// Hold a stable ref to onCancel so the image-load effect doesn't depend
|
||||||
|
// on its identity. Without this, parents that pass an inline `() => …`
|
||||||
|
// re-render the modal on every keystroke / state change, the effect re-
|
||||||
|
// runs, the previous URL.createObjectURL gets revoked WHILE the new img
|
||||||
|
// is still decoding → img.onerror fires ("file not found") → onCancel →
|
||||||
|
// modal flashes open + closes instantly.
|
||||||
|
const onCancelRef = useRef(onCancel);
|
||||||
|
useEffect(() => { onCancelRef.current = onCancel; }, [onCancel]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const url = URL.createObjectURL(file);
|
const url = URL.createObjectURL(file);
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
@@ -50,11 +59,11 @@ export function ImageAnnotator({ file, onCancel, onSave }: Props) {
|
|||||||
};
|
};
|
||||||
img.onerror = () => {
|
img.onerror = () => {
|
||||||
console.error('ImageAnnotator: failed to decode source image');
|
console.error('ImageAnnotator: failed to decode source image');
|
||||||
onCancel();
|
onCancelRef.current();
|
||||||
};
|
};
|
||||||
img.src = url;
|
img.src = url;
|
||||||
return () => URL.revokeObjectURL(url);
|
return () => URL.revokeObjectURL(url);
|
||||||
}, [file, onCancel]);
|
}, [file]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!imageLoaded) return;
|
if (!imageLoaded) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user