iOS (isModal=true) でマリンライナー等の走行中列車を表示した際に
ActionSheet のスライドアップアニメーションが瞬間表示になる問題を修正。
【根本原因】
1. iOS onOpen の発火タイミング問題(最重要)
- ライブラリ内で onOpen が Modal.onShow にバインドされており、
スプリングアニメーション開始「前」に発火する
- onOpen 後に showThrew=true になると通過駅が追加されて高さが増加し
onSheetLayout が再発火 → スプリングがほぼ終点からリスタート
2. useEffect による非同期な高さ変化
- useThroughStations / useStopStationIDs / useTrainDiagramData が
useState([]) で初期化し useEffect で計算していたため
空リスト → フルリストの高さ変化が onSheetLayout をトリガーしていた
3. useAutoScroll の InteractionManager が Reanimated アニメーションを認識しない
【修正内容】
- EachTrainInfoCore: showThrew の初期値を useState(() => !!getCurrentStationData(...))
に変更し、走行中なら最初から true にして高さ変化を防ぐ
- useTrainDiagramData / useThroughStations / useStopStationIDs:
純粋計算関数を抽出し useState lazy initializer で初回レンダリング時から正確な高さを確保
- EachTrainInfo: onOpen/onClose で sheetOpened state を管理し EachTrainInfoCore に渡す
- useAutoScroll: setShowThrew 引数を削除、sheetOpened フラグでスクロールをゲート
34 lines
1.0 KiB
TypeScript
34 lines
1.0 KiB
TypeScript
import { useEffect, MutableRefObject } from 'react';
|
|
|
|
|
|
export const useAutoScroll = (
|
|
points: boolean[] | undefined,
|
|
trainDataWithThrough: string[],
|
|
scrollRef: MutableRefObject<any>,
|
|
isJumped: boolean,
|
|
setIsJumped: (value: boolean) => void,
|
|
sheetOpened: boolean = false
|
|
) => {
|
|
useEffect(() => {
|
|
// ActionSheetのスプリングアニメーション完了後まで待機
|
|
if (!sheetOpened || isJumped || !points?.length || !scrollRef) return;
|
|
|
|
const currentPositionIndex = points.findIndex((d) => d === true);
|
|
if (currentPositionIndex === -1) return;
|
|
|
|
// 5駅以内の場合はスクロールしない
|
|
if (currentPositionIndex < 5) {
|
|
setIsJumped(true);
|
|
return;
|
|
}
|
|
|
|
const scrollPosition = currentPositionIndex * 44 - 50;
|
|
const timer = setTimeout(() => {
|
|
scrollRef.current?.scrollTo({ y: scrollPosition, animated: true });
|
|
setIsJumped(true);
|
|
}, 100);
|
|
|
|
return () => clearTimeout(timer);
|
|
}, [sheetOpened, points, trainDataWithThrough, scrollRef, isJumped, setIsJumped]);
|
|
};
|