【React Native】FlatList.getNativeScrollRef()でよくあるエラーと解決策

2025-05-31

FlatList.getNativeScrollRef() は、React NativeのFlatListコンポーネントが内部的に使用しているネイティブのスクロールコンポーネント(例えば、iOSではUIScrollView、Androidではandroid.widget.ScrollViewなど)への参照(ref)を取得するためのメソッドです。

なぜこれが必要なのか?

通常、React Nativeではコンポーネントを操作するためにRefを使用しますが、FlatListは内部的に多くの最適化を行っており、直接ScrollViewのようなネイティブのスクロールコンポーネントを公開しているわけではありません。

しかし、アニメーションライブラリ(例: react-native-reanimated)など、より低レベルなネイティブのスクロール操作を行いたい場合に、このネイティブなスクロールコンポーネントへの直接的な参照が必要になることがあります。getNativeScrollRef() メソッドは、このような場合に、基盤となるネイティブスクロールコンポーネントへのアクセスを提供します。

使い方

FlatListのRefを介して呼び出すことができます。

import React, { useRef, useEffect } from 'react';
import { FlatList, Text, View } from 'react-native';

const MyList = () => {
  const flatListRef = useRef(null);
  const data = Array.from({ length: 50 }, (_, i) => ({ id: String(i), title: `Item ${i}` }));

  useEffect(() => {
    if (flatListRef.current) {
      // getNativeScrollRef() を使ってネイティブのスクロールリファレンスを取得
      const nativeScrollRef = flatListRef.current.getNativeScrollRef();
      console.log('ネイティブスクロールRef:', nativeScrollRef);

      // ここで nativeScrollRef を使って、特定のネイティブ操作を行うことができる(上級者向け)
      // 例: react-native-reanimated の scrollTo など
    }
  }, []);

  return (
    <FlatList
      ref={flatListRef}
      data={data}
      renderItem={({ item }) => (
        <View style={{ padding: 20, borderBottomWidth: 1, borderColor: '#ccc' }}>
          <Text>{item.title}</Text>
        </View>
      )}
      keyExtractor={(item) => item.id}
    />
  );
};

export default MyList;

上記の例では、useRefを使ってFlatListコンポーネントへの参照を作成し、useEffect内でgetNativeScrollRef()を呼び出してネイティブのスクロールリファレンスを取得しています。

注意点

  • アニメーションライブラリとの連携: react-native-reanimatedなどのアニメーションライブラリでスクロール操作をより細かく制御したい場合に、このメソッドが役立つことがあります。例えば、react-native-reanimatedscrollTo関数は、このネイティブスクロールRefを引数として受け取ることがあります。
  • プラットフォーム依存: 取得されるネイティブのスクロールリファレンスは、iOSやAndroidといったプラットフォームによって異なる型を持ちます。
  • 低レベルなAPI: getNativeScrollRef()は、通常の使用ではほとんど必要ありません。FlatListが提供するscrollToIndexscrollToOffsetなどの高レベルなメソッドで事足りることがほとんどです。


flatListRef.current が null または undefined になる

エラーの状況: flatListRef.current.getNativeScrollRef() を呼び出そうとした際に、「Cannot read property 'getNativeScrollRef' of null (or undefined)」のようなエラーが発生する。

原因: FlatListコンポーネントがまだマウントされていないか、Refが正しく設定されていない可能性があります。FlatListコンポーネントが実際にレンダリングされる前に、Refが参照可能になる前にメソッドを呼び出そうとしていることがよくあります。

トラブルシューティング:

  • 条件付きレンダリング: FlatListが条件付きでレンダリングされる場合(例: データがロードされるまで表示されないなど)は、flatListRef.currentnullでないことを必ず確認してからアクセスしてください。
  • useEffect の使用と依存関係: getNativeScrollRef() を呼び出す際は、FlatListがレンダリングされてRefがセットされた後に実行されるように、useEffectフックを使用し、依存関係にflatListRef(または関連する状態)を含めるようにしてください。
    import React, { useRef, useEffect } from 'react';
    import { FlatList } from 'react-native';
    
    const MyList = () => {
      const flatListRef = useRef(null);
    
      useEffect(() => {
        if (flatListRef.current) {
          const nativeScrollRef = flatListRef.current.getNativeScrollRef();
          console.log('ネイティブスクロールRef:', nativeScrollRef);
        }
      }, [flatListRef.current]); // flatListRef.current が変更されたときに実行
      // または、コンポーネントがマウントされた後に一度だけ実行したい場合は空の配列 `[]`
      // しかし、もし FlatList が条件付きでレンダリングされる場合などは、ref.currentのチェックが必須です
    
      return (
        <FlatList
          ref={flatListRef}
          data={/* ... */}
          renderItem={/* ... */}
          keyExtractor={/* ... */}
        />
      );
    };
    

getNativeScrollRef が関数ではないというエラー

エラーの状況: 「flatListRef.current.getNativeScrollRef is not a function」のようなエラーが発生する。

原因: これは通常、以下のいずれかの理由で発生します。

  • ScrollViewのRefを取得しようとしている: FlatListではなく、内部のScrollViewのRefを直接取得しようとしていると、このようなエラーになる場合があります。
  • 誤ったRefの対象: FlatList以外のコンポーネントのRefに対してgetNativeScrollRef()を呼び出している可能性があります。
  • 古いReact Nativeバージョン: getNativeScrollRef() は比較的新しい機能です。古いReact Nativeのバージョンを使用している場合、このメソッドが存在しない可能性があります。

トラブルシューティング:

  • FlatListのRefであることを確認: 意図的にScrollViewなどのRefを取得しているわけではないことを確認してください。getNativeScrollRef()FlatListに特化したメソッドです。
  • Refが正しいコンポーネントにアタッチされているか確認: ref={flatListRef}が正しくFlatListコンポーネントにアタッチされているか再確認してください。
  • React Nativeのバージョン確認: 使用しているReact Nativeのバージョンが、getNativeScrollRef()をサポートしているか確認してください。最新のReact Nativeにアップデートすることを検討してください。

ネイティブのスクロールリファレンスが期待通りに機能しない

エラーの状況: getNativeScrollRef() で取得したネイティブのリファレンスを使って、アニメーションライブラリなどでスクロール操作を試みても、何も起こらないか、予期しない動作をする。

原因:

  • FlatListの最適化の影響: FlatListはパフォーマンスのために多くの最適化(仮想化など)を行っています。これらの最適化が、ネイティブレベルでの直接的なスクロール操作に影響を与える可能性があります。
  • アニメーションライブラリのバージョンの不一致: 使用しているアニメーションライブラリ(例: react-native-reanimated)が、React NativeやFlatListの特定のバージョンと互換性がない場合があります。
  • 間違ったネイティブ操作: 取得したネイティブリファレンスに対する操作が、そのプラットフォームのネイティブコンポーネントで期待される動作と一致していない可能性があります。
  • 非同期性: ネイティブのリファレンスに対する操作は非同期である場合があります。

トラブルシューティング:

  • FlatListの標準メソッドの使用検討: 多くのスクロール操作は、FlatList自体が提供するscrollToIndexscrollToOffsetなどのメソッドで実現できます。これらの高レベルなAPIで目的が達成できる場合は、getNativeScrollRef()を使う必要がないかもしれません。
  • シンプルなケースで試す: まずはFlatList以外の簡単なScrollViewでネイティブスクロール操作が機能するかどうかをテストし、問題がFlatListに固有のものか、それともネイティブ操作全般に関するものかを切り分けてください。
  • デバッグログの出力: 取得したnativeScrollRefの内容をconsole.log()で出力し、どのようなオブジェクトが返されているかを確認してください。プラットフォーム(iOS/Android)によって異なる可能性があります。
  • アニメーションライブラリのドキュメント参照: react-native-reanimatedなどのライブラリを使用している場合は、そのライブラリのドキュメントを詳しく参照し、getNativeScrollRef()から取得した参照をどのように使用すべきか確認してください。特定のプロパティやメソッドにアクセスする必要があるかもしれません。
  • 非同期操作の考慮: ネイティブの操作が非同期である可能性があるため、操作の完了を待つ必要がある場合があります。

Androidで問題が発生する (特にreact-native-webを使用している場合)

エラーの状況: iOSでは動作するが、Android(またはreact-native-web)でgetNativeScrollRef()が機能しない、またはエラーになる。

原因:

  • react-native-webのサポート: react-native-webは、すべてのネイティブモジュールやメソッドを完全にサポートしているわけではありません。過去にはgetNativeScrollRefreact-native-webで利用できないという問題が報告されていました(現在は修正されている可能性がありますが、古いバージョンでは起こりえます)。
  • プラットフォームの差異: ネイティブコンポーネントの実装はプラットフォームによって異なります。Androidでは異なるRefの構造やメソッドが必要になる場合があります。

トラブルシューティング:

  • react-native-webの最新情報確認: react-native-webを使用している場合は、そのプロジェクトのGitHubリポジトリのissueやリリースノートを確認し、getNativeScrollRef()のサポート状況に関する情報を探してください。最新版にアップデートすることで解決する場合があります。
  • プラットフォーム固有のコード: 必要であれば、Platform.OSを使用してプラットフォームごとに異なるロジックを記述することを検討してください。


以下に、FlatList.getNativeScrollRef()の使用例をいくつか示します。

例1: ネイティブスクロールリファレンスをログに出力する(基本的な使い方)

これは最も基本的な例で、FlatListのネイティブスクロールリファレンスがどのように取得されるかを示します。

import React, { useRef, useEffect } from 'react';
import { FlatList, Text, View, StyleSheet } from 'react-native';

const DATA = Array.from({ length: 50 }, (_, i) => ({ id: String(i), title: `Item ${i}` }));

const BasicNativeScrollRefExample = () => {
  const flatListRef = useRef(null);

  useEffect(() => {
    // コンポーネントがマウントされ、FlatList の Ref が利用可能になったら
    if (flatListRef.current) {
      // getNativeScrollRef() を使ってネイティブのスクロールリファレンスを取得
      const nativeScrollRef = flatListRef.current.getNativeScrollRef();

      // この nativeScrollRef は、プラットフォーム固有のネイティブビューの参照です。
      // iOSでは UIScrollView、Androidでは android.widget.ScrollView など。
      // 通常、直接操作することはありませんが、その存在を確認できます。
      console.log('取得したネイティブスクロールRef:', nativeScrollRef);

      // (開発環境のコンソールで確認してください)
      // 例: iOSシミュレータでは、<RCTScrollView: 0x...> のようなオブジェクトが表示されることがあります。
      // Androidエミュレータでは、<ScrollView: @...> のようなオブジェクトが表示されることがあります。
    }
  }, []); // コンポーネントのマウント時に一度だけ実行

  const renderItem = ({ item }) => (
    <View style={styles.item}>
      <Text style={styles.title}>{item.title}</Text>
    </View>
  );

  return (
    <FlatList
      ref={flatListRef}
      data={DATA}
      renderItem={renderItem}
      keyExtractor={(item) => item.id}
      contentContainerStyle={styles.contentContainer}
    />
  );
};

const styles = StyleSheet.create({
  contentContainer: {
    paddingTop: 20,
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
    borderRadius: 8,
  },
  title: {
    fontSize: 20,
  },
});

export default BasicNativeScrollRefExample;

例2: react-native-reanimatedscrollTo を組み合わせて使用する

これはgetNativeScrollRef()の最も一般的なユースケースです。react-native-reanimatedscrollTo関数は、UIスレッドでスクロール操作を実行するためにネイティブのスクロールリファレンスを必要とします。

前提:

  • アプリケーションを再ビルド(npx react-native run-ios / run-android)すること。
  • babel.config.jsreact-native-reanimated/plugin が追加されていること。
    module.exports = {
      presets: ['module:@react-native/babel-preset'],
      plugins: [
        'react-native-reanimated/plugin', // これを追加
      ],
    };
    
  • react-native-reanimatedがインストールされていること。
    npm install react-native-reanimated
    # または yarn add react-native-reanimated
    
import React, { useRef, useEffect } from 'react';
import { FlatList, Text, View, StyleSheet, Button, Dimensions } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedRef,
  scrollTo, // reanimated の scrollTo 関数
  useAnimatedStyle,
  runOnUI,
} from 'react-native-reanimated';

const { height } = Dimensions.get('window');
const ITEM_HEIGHT = 80; // アイテムの高さ + マージン

const DATA = Array.from({ length: 50 }, (_, i) => ({ id: String(i), title: `Item ${i}` }));

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

const ReanimatedScrollExample = () => {
  const animatedFlatListRef = useAnimatedRef(); // reanimated の Ref を使用
  const scrollOffset = useSharedValue(0);

  const scrollToIndex = (index) => {
    // UIスレッドで実行
    runOnUI(() => {
      // getNativeScrollRef() で取得したネイティブ Ref を scrollTo に渡す
      // AnimatedFlatList の Ref から直接 getNativeScrollRef() を呼び出す
      const nativeScrollRef = animatedFlatListRef.current.getNativeScrollRef();

      if (nativeScrollRef) {
        // desiredOffset を計算
        const desiredOffset = index * ITEM_HEIGHT; // 例: 各アイテムの高さで計算

        // scrollTo 関数で指定のオフセットへスクロール
        // scrollTo(ref, xOffset, yOffset, animated)
        scrollTo(nativeScrollRef, 0, desiredOffset, true); // y軸にスクロール、アニメーションを有効にする
      }
    })(); // runOnUI の関数を即時実行
  };

  const renderItem = ({ item }) => (
    <View style={styles.item}>
      <Text style={styles.title}>{item.title}</Text>
    </View>
  );

  return (
    <View style={styles.container}>
      <Button title="10番目のアイテムにスクロール" onPress={() => scrollToIndex(9)} />
      <Button title="25番目のアイテムにスクロール" onPress={() => scrollToIndex(24)} />
      <Button title="一番下へスクロール" onPress={() => scrollToIndex(DATA.length - 1)} />

      <AnimatedFlatList
        ref={animatedFlatListRef} // AnimatedFlatListRef をアタッチ
        data={DATA}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        contentContainerStyle={styles.contentContainer}
        // スクロールイベントを Reanimated でトラッキングしたい場合は onScroll を使用
        // onScroll={useAnimatedScrollHandler((event) => {
        //   scrollOffset.value = event.contentOffset.y;
        // })}
        // scrollEventThrottle は onScroll の発火頻度を制御
        scrollEventThrottle={16}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  contentContainer: {
    paddingBottom: 20, // スクロール可能領域の底に余白を追加
  },
  item: {
    backgroundColor: '#e0f7fa',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
    borderRadius: 8,
    height: 64, // 例としてアイテムの高さ
    justifyContent: 'center',
  },
  title: {
    fontSize: 18,
    color: '#00796b',
  },
});

export default ReanimatedScrollExample;

例3: FlatListmaintainVisibleContentPosition との連携(高度なケース)

maintainVisibleContentPosition は、チャットアプリケーションなどで新しいアイテムがリストの先頭や末尾に追加されたときに、現在のスクロール位置を維持するための高度なプロパティです。getNativeScrollRef()を直接使用することは稀ですが、内部的にネイティブスクロールの動作に影響を与える可能性があるため、知っておくと良いでしょう。

このプロパティ自体がgetNativeScrollRef()を直接使う例ではありませんが、FlatListのスクロール動作を低レベルで制御する際の知識として関連性が高いです。

import React, { useState, useRef, useEffect, useCallback } from 'react';
import { FlatList, Text, View, StyleSheet, Button } from 'react-native';

const INITIAL_DATA_COUNT = 10;
const ADD_COUNT = 5;

const generateData = (count) => {
  return Array.from({ length: count }, (_, i) => ({ id: String(i), title: `Item ${i}` }));
};

const ChatLikeListExample = () => {
  const [data, setData] = useState(generateData(INITIAL_DATA_COUNT));
  const flatListRef = useRef(null);

  const addItemsToTop = useCallback(() => {
    const newItems = Array.from(
      { length: ADD_COUNT },
      (_, i) => ({ id: `new-top-${Math.random()}`, title: `New Top Item ${i}` })
    );
    setData((prevData) => [...newItems, ...prevData]);
  }, []);

  const addItemsToBottom = useCallback(() => {
    const newItems = Array.from(
      { length: ADD_COUNT },
      (_, i) => ({ id: `new-bottom-${Math.random()}`, title: `New Bottom Item ${i}` })
    );
    setData((prevData) => [...prevData, ...newItems]);
  }, []);

  useEffect(() => {
    // 必要であれば、ここで flatListRef.current.getNativeScrollRef() を使って
    // ネイティブのスクロールリファレンスにアクセスできますが、
    // maintainVisibleContentPosition を使う場合は、FlatListが自動的に処理します。
    // console.log(flatListRef.current?.getNativeScrollRef());
  }, [data]); // データが更新された際にRefを確認したい場合

  const renderItem = ({ item }) => (
    <View style={styles.item}>
      <Text style={styles.title}>{item.title}</Text>
    </View>
  );

  return (
    <View style={styles.container}>
      <View style={styles.buttonContainer}>
        <Button title="上部にアイテムを追加" onPress={addItemsToTop} />
        <Button title="下部にアイテムを追加" onPress={addItemsToBottom} />
      </View>
      <FlatList
        ref={flatListRef}
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        contentContainerStyle={styles.contentContainer}
        // maintainVisibleContentPosition を有効にすると、
        // 上部に新しいアイテムが追加されたときに、スクロール位置を維持しようとします。
        // これはチャットアプリなどで非常に便利です。
        maintainVisibleContentPosition={{
          minIndexForVisible: 0, // 常に一番上のアイテムが見えるように試みる
          autoscrollToTopThreshold: 0, // 上部に自動スクロールする閾値
        }}
        // invert を true にして、チャットのように下から上にアイテムを表示する
        inverted
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginBottom: 10,
  },
  contentContainer: {
    paddingBottom: 20,
  },
  item: {
    backgroundColor: '#ffe0b2',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
    borderRadius: 8,
    minHeight: 60,
    justifyContent: 'center',
  },
  title: {
    fontSize: 16,
    color: '#e65100',
  },
});

export default ChatLikeListExample;


しかし、多くの一般的なユースケースでは、このメソッドを使う必要はありません。FlatList自体が豊富な高レベルAPIを提供しており、それらを使うことでスクロールの制御が可能です。また、よりパフォーマンスを重視するリストコンポーネントへの置き換えも選択肢となります。

FlatListの標準的なメソッドを使用する

ほとんどのスクロール制御のニーズは、FlatList自体が提供する以下のメソッドで満たすことができます。これらは宣言的であり、プラットフォームの差異を抽象化してくれるため、通常はこちらの使用が推奨されます。

  • scrollToItem(params: object): 特定のアイテムオブジェクトまでスクロールします(scrollToIndexよりも便利ですが、リストのデータサイズが大きい場合はscrollToIndex + getItemLayoutの方が効率的です)。

    • item (object): スクロール先のアイテムオブジェクト(必須)。
    • animated (boolean): スクロールをアニメーションさせるかどうか。
    • viewPosition (number): スクロール先のアイテムをビューのどこに配置するか。 :
    // const targetItem = DATA[DATA.length - 1]; // 例: 最後のアイテム
    // <Button title="指定アイテムへスクロール" onPress={() => flatListRef.current.scrollToItem({ item: targetItem, animated: true })} />
    
  • scrollToEnd(params?: { animated?: boolean }): リストの末尾までスクロールします。

    • animated (boolean): スクロールをアニメーションさせるかどうか(デフォルトはtrue)。 :
    // <Button title="一番下へスクロール" onPress={() => flatListRef.current.scrollToEnd({ animated: true })} />
    
  • scrollToOffset(params: object): 指定したオフセット(ピクセル単位)までスクロールします。

    • offset (number): スクロール先のピクセルオフセット(必須)。horizontaltrueの場合はX軸、それ以外はY軸。
    • animated (boolean): スクロールをアニメーションさせるかどうか(デフォルトはtrue)。 :
    // 上記の例の Button 部分を以下のように変更
    // <Button title="上から200pxにスクロール" onPress={() => flatListRef.current.scrollToOffset({ offset: 200, animated: true })} />
    
  • scrollToIndex(params: object): 特定のインデックスのアイテムまでスクロールします。

    • index (number): スクロール先のアイテムのインデックス(必須)。
    • animated (boolean): スクロールをアニメーションさせるかどうか(デフォルトはtrue)。
    • viewOffset (number): 最終的なターゲット位置からの固定オフセット(ピクセル)。
    • viewPosition (number): スクロール先のアイテムをビューのどこに配置するか(0: トップ、0.5: 中央、1: ボトム)。 :
    import React, { useRef } from 'react';
    import { FlatList, Button, View, Text, StyleSheet } from 'react-native';
    
    const DATA = Array.from({ length: 100 }, (_, i) => ({ id: String(i), title: `Item ${i}` }));
    
    function FlatListStandardMethods() {
      const flatListRef = useRef(null);
    
      const scrollToItemByIndex = (index) => {
        flatListRef.current.scrollToIndex({
          index: index,
          animated: true,
          viewPosition: 0.5, // 中央に表示
        });
      };
    
      return (
        <View style={styles.container}>
          <Button title="50番目のアイテムにスクロール" onPress={() => scrollToItemByIndex(49)} />
          <FlatList
            ref={flatListRef}
            data={DATA}
            renderItem={({ item }) => (
              <View style={styles.item}>
                <Text>{item.title}</Text>
              </View>
            )}
            keyExtractor={(item) => item.id}
            getItemLayout={(data, index) => (
              { length: 50, offset: 50 * index, index } // パフォーマンス向上のため設定を推奨
            )}
          />
        </View>
      );
    }
    const styles = StyleSheet.create({
      container: { flex: 1, paddingTop: 50 },
      item: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', height: 50 },
    });
    export default FlatListStandardMethods;
    

ScrollViewの直接操作(FlatListの代わりに)

もしリストが非常に短く、仮想化の恩恵をあまり受けない場合(例: 画面に収まる程度のアイテム数)、FlatListの代わりにScrollViewを使用することもできます。ScrollViewFlatListよりもシンプルで、そのRefを介して直接scrollToメソッドを呼び出すことができます。

import React, { useRef } from 'react';
import { ScrollView, Button, View, Text, StyleSheet } from 'react-native';

function ScrollViewDirectControl() {
  const scrollViewRef = useRef(null);

  const scrollToTop = () => {
    scrollViewRef.current.scrollTo({ x: 0, y: 0, animated: true });
  };

  const scrollToBottom = () => {
    scrollViewRef.current.scrollToEnd({ animated: true });
  };

  return (
    <View style={styles.container}>
      <Button title="一番上へスクロール" onPress={scrollToTop} />
      <Button title="一番下へスクロール" onPress={scrollToBottom} />
      <ScrollView
        ref={scrollViewRef}
        style={styles.scrollView}
        contentContainerStyle={styles.scrollViewContent}
      >
        {Array.from({ length: 50 }, (_, i) => (
          <View key={i} style={styles.item}>
            <Text>ScrollView Item {i}</Text>
          </View>
        ))}
      </ScrollView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, paddingTop: 50 },
  scrollView: { flex: 1 },
  scrollViewContent: { paddingBottom: 20 },
  item: { padding: 15, borderBottomWidth: 1, borderBottomColor: '#eee' },
});
export default ScrollViewDirectControl;

注意: ScrollViewはすべてのコンテンツを一度にレンダリングするため、リストが長くなるとパフォーマンスの問題が発生する可能性があります。

FlashListの使用 (Shopify製)

もしFlatListのパフォーマンスに不満があり、getNativeScrollRef()のような低レベルな最適化を検討しているなら、Shopifyが開発したFlashListを検討する価値があります。FlashListFlatListとほぼ同じAPIを持ちながら、より効率的なビューのリサイクル機構によって、非常に大規模なリストでも優れたパフォーマンスを発揮します。

FlashListFlatListと同様にscrollToIndexscrollToOffsetなどのメソッドを提供しており、通常はgetNativeScrollRef()のような低レベルなAPIに頼る必要はありません。

前提:

  • @shopify/flash-listをインストール
    npm install @shopify/flash-list
    # または yarn add @shopify/flash-list
    

: (APIはFlatListとほぼ同じです)

import React, { useRef } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import { FlashList } from '@shopify/flash-list';

const DATA = Array.from({ length: 5000 }, (_, i) => ({ id: String(i), title: `FlashList Item ${i}` }));

function FlashListExample() {
  const flashListRef = useRef(null);

  const scrollToIndex = (index) => {
    flashListRef.current.scrollToIndex({
      index: index,
      animated: true,
      viewPosition: 0.5,
    });
  };

  return (
    <View style={styles.container}>
      <Button title="2500番目のアイテムにスクロール (FlashList)" onPress={() => scrollToIndex(2499)} />
      <FlashList
        ref={flashListRef}
        data={DATA}
        renderItem={({ item }) => (
          <View style={styles.item}>
            <Text>{item.title}</Text>
          </View>
        )}
        estimatedItemSize={50} // 必須または強く推奨
        keyExtractor={(item) => item.id}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, paddingTop: 50 },
  item: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', height: 50 },
});

export default FlashListExample;

ポイント: FlashListでは、estimatedItemSizeプロパティの設定がパフォーマンスのために非常に重要です。

FlatList.getNativeScrollRef()は特定のニッチなユースケース(主にreact-native-reanimatedとの連携)で強力ですが、ほとんどのスクロール制御の要件は、FlatListの標準メソッド(scrollToIndex, scrollToOffset, scrollToEnd)で十分に満たせます。