【3回】Expo・ReactNativeのScrollView、ListViewの使い方

プログラミング
スポンサーリンク

このブログについて

  • Expoを使いつつ、ReactNative のアプリ開発についてまとめていきます。
  • 必要に応じて、ライブラリなどの紹介します
  • チャプターごとの状態を GitHub で管理するので、必要であればクローンしてください。

こんな方にオススメ

  • React、TypeScript などについては学んでいる
  • スマホアプリケーションの開発に興味がある

前提ツールのバージョン

ツール バージョン
node 22.19.0
pnpm 10.15.1
expo(SDK) 54

過去の投稿

【1回】Expo・ReactNativeの環境構築
このブログについてExpoを使いつつ、ReactNative のアプリ開発についてまとめていきます。必要に応じて、ライブラリなどの紹介しますチャプターごとの状態を GitHub で管理するので、必要であればクローンしてください。こんな方にオ...
【2回】Expo・ReactNativeのView・Text・TextInput・Buttonの使い方
このブログについて Expoを使いつつ、ReactNative のアプリ開発についてまとめていきます。 必要に応じて、ライブラリなどの紹介します チャプターごとの状態を GitHub で管理するので、必要であればクローンしてください。こんな...

事前準備

ファイル作成

  • app/(Home)/blogs.tsx

追記・修正


<Stack>
// ここから
<Stack.Screen
name="blogs"
options={{ title: "ブログ", headerShown: false }}
/>
// ここまで
</Stack>

view raw

_layout.tsx

hosted with ❤ by GitHub


import { useRouter } from "expo-router";
export default function Home() {
const [email, setEmail] = React.useState("");
const router = useRouter();
// ・・・
return (
<Button
title="送信"
onPress={() => router.push("/(Home)/blogs")}
/>
// ・・・
);
}

view raw

index.tsx

hosted with ❤ by GitHub

ScrollViewとFlatList

サンプル

前回、Viewというタグを紹介しました。Web系ならdivタグに対してoverflow: scrollを設定できますがExpoでは ScrollViewFlatList を用いる必要がある。

コードサンプル


import {
FlatList,
ScrollView,
StyleSheet,
Text,
View,
ViewStyle,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
type BlogItemProps = {
title: string;
content: string;
style?: ViewStyle;
};
function BlogItem({ title, content, style }: BlogItemProps) {
return (
<View style={[styles.item, style]}>
<Text style={styles.itemTitle}>{title}</Text>
<Text style={styles.itemContent}>{content}</Text>
</View>
);
}
export default function Blogs() {
const blogs = [
{
id: 1,
title: "Blog 1",
content: "Content 1",
},
// 省略
];
// 横スクロール用のデータ
const horizontalScrollItems = blogs.map((blog) => (
<BlogItem
key={blog.id}
title={blog.title}
content={blog.content}
style={styles.horizontalScrollItem}
/>
));
// 縦スクロール用のデータ
const verticalScrollItems = blogs.map((blog) => (
<BlogItem
key={blog.id}
title={blog.title}
content={blog.content}
style={styles.verticalScrollItem}
/>
));
// FlatList用のレンダリング関数(横スクロール用)
const renderHorizontalItem = ({ item }: BlogItemProps }) => (
<BlogItem
title={item.title}
content={item.content}
style={styles.horizontalListItem}
/>
);
// FlatList用のレンダリング関数(縦スクロール用)
const renderVerticalItem = ({ item }: { item: BlogItemProps}) => (
<BlogItem
title={item.title}
content={item.content}
style={styles.verticalListItem}
/>
);
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
{/* 上部: 横スクロールのScrollView */}
<View style={styles.scrollViewContainer}>
<Text style={styles.sectionTitle}>ScrollView(横スクロール)</Text>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.horizontalScrollView}
contentContainerStyle={styles.horizontalScrollViewContent}
>
{horizontalScrollItems}
</ScrollView>
</View>
{/* 中央: 縦スクロールのScrollView */}
<View style={styles.scrollViewContainer}>
<Text style={styles.sectionTitle}>ScrollView(縦スクロール)</Text>
<ScrollView
showsVerticalScrollIndicator={false}
style={styles.verticalScrollView}
contentContainerStyle={styles.verticalScrollViewContent}
>
{verticalScrollItems}
</ScrollView>
</View>
{/* 下部: 横スクロールのFlatList */}
<View style={styles.listViewContainer}>
<Text style={styles.sectionTitle}>FlatList(横スクロール)</Text>
<FlatList
data={blogs}
renderItem={renderHorizontalItem}
keyExtractor={(item) => item.id.toString()}
horizontal
showsHorizontalScrollIndicator={false}
style={styles.horizontalFlatList}
contentContainerStyle={styles.horizontalFlatListContent}
/>
</View>
{/* 最下部: 縦スクロールのFlatList */}
<View style={styles.listViewContainer}>
<Text style={styles.sectionTitle}>FlatList(縦スクロール)</Text>
<FlatList
data={blogs}
renderItem={renderVerticalItem}
keyExtractor={(item) => item.id.toString()}
showsVerticalScrollIndicator={false}
style={styles.verticalFlatList}
contentContainerStyle={styles.verticalFlatListContent}
/>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
// 省略
});

view raw

blogs.tsx

hosted with ❤ by GitHub

ScrollView

ScrollView · React Native
Component that wraps platform ScrollView while providing integration with touch locking "responder" system.
Props 備考
horizontal boolean 横向きスクロールに変更する。
デフォルトは縦向き。
true: 横向き
showsHorizontalScrollIndicator boolean 横向きのスクロールバーの表示・非表示設定
true: 表示 false: 非表示
showsVerticalScrollIndicator boolean 縦向きのスクロールバーの表示・非表示設定
true: 表示 false: 非表示

FlatView

FlatList · React Native
A performant interface for rendering basic, flat lists, supporting the most handy features:
Props 備考 必須
data Array 表示するデータの配列。
renderItem (item, index) => JSX.Element dataを整形して表示する コンポーネントを定義する。
itemはdataの要素。
keyExtractor (item) => string renderItemで描画された
horizontal boolean 横向きスクロールに変更する。
デフォルトは縦向き。
true: 横向き
showsHorizontalScrollIndicator boolean 横向きのスクロールバーの表示・非表示設定
true: 表示 false: 非表示
showsVerticalScrollIndicator boolean 縦向きのスクロールバーの表示・非表示設定
true: 表示 false: 非表示

どっちを使えば良いか

公式的には以下のような記載があります。

ScrollView renders all its react child components at once, but this has a performance downside.
Imagine you have a very long list of items you want to display, maybe several screens worth of content. Creating JS components and native views for everything all at once, much of which may not even be shown, will contribute to slow rendering and increased memory usage.

ScrollViewだとリストの内容を1度に描画されるので、量が多いとパフォーマンスが落ちる。
無限スクロールを実装する場合などは FlatView のほうがよい。
他にも FlatView だと、HeaderやFooterなどTable的なことも標準で用意されている。

一方で、データを持たない場合(画面のスクロール)などは ScrollView を使った方が良いと思う。

決まった型があるデータの有無で分けて良さそうな気はする。

まとめ

  • ScrollViewとFlatListについて紹介しました
  • データの型が決まっている場合や量が多い場合はFlatListを使う
  • スクリーン全体など型がない場合はScrollViewを使う

参考資料

https://docs.expo.dev
Build one JavaScript/TypeScript project that runs natively on all your users' devices.
React Native · Learn once, write anywhere
A framework for building native apps for Android, iOS, and more using React

コメント

タイトルとURLをコピーしました