React NativeのText#onPressでよくあるエラーと解決策

2025-06-06

React Nativeにおける Text#onPress の説明

React Native(リアクト・ネイティブ)プログラミングにおいて、<Text> コンポーネントは、UI上にテキストを表示するために使用されます。この <Text> コンポーネントには、onPress という非常に重要なプロパティ(props)があります。

onPress とは何か?

onPress は、<Text> コンポーネントがタップされたり、クリックされたりしたときに実行される関数を指定するためのプロパティです。ユーザーが画面上のテキストに触れたり、マウスでクリックしたりすると、この onPress に設定された関数が自動的に呼び出されます。

なぜ Text#onPress が必要なのか?

通常、React Nativeでインタラクティブな要素を作成するには、<Button><TouchableOpacity> のようなコンポーネントが使われます。しかし、次のような状況では <Text#onPress> が非常に便利です。

  1. シンプルなテキストのインタラクション
    ボタンとしてデザインされていない、単なるテキストをタップ可能にしたい場合。例えば、「利用規約」や「プライバシーポリシー」のhttps://www.google.com/search?q=%E3%83%AA%E3%83%B3%E3%82%AFなど。
  2. 柔軟なスタイリング
    <Button> コンポーネントはスタイルに関する制約がある場合がありますが、<Text> は非常に自由にスタイルを適用できます。onPress を使うことで、スタイリングの自由度を保ちつつ、タップ可能なテキストを作成できます。

使用例(コードスニペット)

以下に、Text#onPress の基本的な使用例を示します。

import React from 'react';
import { View, Text, Alert, StyleSheet } from 'react-native';

const MyTextComponent = () => {
  const handlePress = () => {
    // テキストがタップされたときに実行される処理
    Alert.alert('お知らせ', 'テキストがタップされました!');
  };

  const handleLinkPress = () => {
    Alert.alert('リンク', 'プライバシーポリシーが開かれます。');
    // 実際には、ここでWebviewを開いたり、別の画面に遷移したりする処理を記述します
  };

  return (
    <View style={styles.container}>
      {/* 1. シンプルなタップ可能なテキスト */}
      <Text onPress={handlePress} style={styles.tapText}>
        このテキストをタップしてください
      </Text>

      {/* 2. リンクのようなテキスト */}
      <Text onPress={handleLinkPress} style={styles.linkText}>
        プライバシーポリシー
      </Text>

      {/* 3. 部分的にインタラクティブなテキスト(ネストされたText) */}
      <Text>
        詳細については
        <Text onPress={() => Alert.alert('補足', 'さらに詳しい情報!')} style={styles.inlineLink}>
          こちら
        </Text>
        をご覧ください。
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  tapText: {
    fontSize: 18,
    color: 'blue',
    padding: 10,
    borderWidth: 1,
    borderColor: 'gray',
    marginBottom: 20,
  },
  linkText: {
    fontSize: 16,
    color: 'purple',
    textDecorationLine: 'underline', // 下線を追加してリンクのように見せる
    marginBottom: 20,
  },
  inlineLink: {
    color: 'green',
    fontWeight: 'bold',
    textDecorationLine: 'underline',
  },
});

export default MyTextComponent;
  • もしテキスト全体を囲むようにしてタップ可能な領域を広げたい場合は、<TouchableOpacity><Pressable> の中に <Text> を入れる方法も検討してください。この場合、<TouchableOpacity onPress={...}> <Text>...</Text> </TouchableOpacity> のように記述します。
  • <Text> コンポーネントの onPress は、そのテキストがタップされたときにのみ反応します。テキスト以外の余白部分をタップしても何も起こりません。


React Native Text#onPress における一般的なエラーとトラブルシューティング

Text#onPress は非常に便利ですが、使用する際にいくつかの一般的な落とし穴があります。ここでは、それらのエラーと、その解決策について解説します。

onPress が反応しない(イベントが発火しない)

最もよくある問題です。テキストをタップしても、設定した関数が実行されないケースです。

考えられる原因と解決策

  • 原因C: Text コンポーネントが実際にレンダリングされていない。

    • 説明
      条件付きレンダリング(if 文など)によって、そもそも Text コンポーネントが画面に表示されていない可能性があります。
    • 解決策
      • デバッガーやログ出力を使って、Text コンポーネントがレンダリングされるべき条件が満たされているか確認します。
  • 原因B: テキストが他のコンポーネントの下に隠れている。

    • 説明
      レイアウトの問題で、Text コンポーネントが別のコンポーネントの背後に隠れてしまっている場合があります。この場合、タップイベントはその隠しているコンポーネントに吸収されてしまい、Text は反応しません。
    • 解決策
      • React Native Debuggerの「Element」タブや、Chrome DevToolsの「Elements」タブ(ウェブでデバッグしている場合)で、Text コンポーネントが正しくレンダリングされているか、他の要素に覆い隠されていないかを確認します。
      • zIndexposition プロパティを使って、要素の重ね順を調整してみてください。
      • 親コンポーネントに overflow: 'hidden' などが設定されていないか確認します。
    • 説明
      onPress プロパティには、実行可能な関数を渡す必要があります。誤って関数の呼び出し結果(()が付いている)や、定義されていない変数を渡してしまうことがあります。
    • 間違った例
      <Text onPress={myFunction()}> {/* myFunctionの実行結果が渡される */}
        Tap Me
      </Text>
      
    • 正しい例
      <Text onPress={myFunction}> {/* 関数そのものが渡される */}
        Tap Me
      </Text>
      // またはアロー関数で直接定義
      <Text onPress={() => myFunction()}>
        Tap Me
      </Text>
      
    • 解決策
      onPress には、関数名そのもの、またはアロー関数を渡すようにしてください。

タップ可能な領域が狭すぎる/広すぎる

onPress は反応するが、タップしにくい、または意図しない範囲が反応してしまうケースです。

考えられる原因と解決策

  • 原因B: 親のコンポーネントがタップイベントを吸収している。

    • 説明
      親の View などに onPress が設定されている場合、その内部にある TextonPress が正しく動作しないことがあります。イベントの伝播(event bubbling)が問題になることがあります。
    • 解決策
      • 親と子で重複して onPress を設定している場合は、どちらか一方に統一するか、イベントの伝播を考慮した設計にします。React NativeではWebのように event.stopPropagation() を直接使うことは一般的ではありませんが、設計の見直しが必要です。
  • 原因A: Text コンポーネント自体の領域が小さい。

    • 説明
      Text コンポーネントは、その内容(テキスト)の大きさに応じて領域が決まります。文字数が少ないと、タップできる領域が非常に狭くなります。
    • 解決策
      • padding を追加する
        Text コンポーネントに padding スタイルを追加して、タップ可能な領域を広げます。
        <Text onPress={handlePress} style={{ padding: 10 }}> {/* 周囲に10pxのパディング */}
          短
        </Text>
        
      • TouchableOpacity や Pressable を使う
        テキスト自体が持つインタラクションエリアでは不十分な場合、<TouchableOpacity><Pressable><Text> を囲むのが最も一般的な解決策です。これらのコンポーネントは、内部の要素のサイズに関わらず、独自のタップ領域を提供します。
        import { TouchableOpacity, Text } from 'react-native';
        
        <TouchableOpacity onPress={handlePress}>
          <Text>タップしにくいテキスト</Text>
        </TouchableOpacity>
        

スタイリングと onPress の競合

onPress を追加したことで、テキストの見た目が変わってしまう、または期待通りにスタイルが適用されない。

考えられる原因と解決策

  • 原因A: Text コンポーネントに不適切なスタイルが適用されている。
    • 説明
      Text コンポーネントに width, height, flex などのレイアウトプロパティを直接適用しようとすると、期待通りの動作をしないことがあります。Text はインライン要素のように振る舞うため、これらのプロパティは通常 View に適用されます。
    • 解決策
      • テキストの配置やサイズを制御したい場合は、TextView で囲み、その View にレイアウト関連のスタイル(width, height, flex, alignItems, justifyContent など)を適用します。
        <View style={{ width: 100, height: 50, justifyContent: 'center', alignItems: 'center' }}>
          <Text onPress={handlePress}>中央</Text>
        </View>
        
      • Text コンポーネントには、fontSize, color, fontFamily, fontWeight, textAlign, textDecorationLine などのテキスト関連のスタイルを適用します。

ネストされた Text の onPress が反応しない

複数の Text コンポーネントがネストされており、内部の TextonPress が反応しない。

考えられる原因と解決策

  • 原因A: イベントの伝播(Propagation)。
    • 説明
      外側の Text や他のタップ可能なコンポーネントが、内側の Text よりも先にイベントを処理してしまっている可能性があります。React Nativeのタップイベントは、基本的に親から子へと伝播し、最後にそのイベントを処理したコンポーネントが消費します。
    • 解決策
      • React NativeはWebのDOMイベントモデルとは少し異なるため、ネストされたタップ可能な要素の扱いには注意が必要です。最も安全なのは、ネストされた <Text>onPress を設定し、外側の <Text> には onPress を設定しないことです。
      • もし外側と内側の両方をタップ可能にしたい場合は、onPress のロジックを慎重に設計し、どちらのイベントが優先されるべきかを明確にする必要があります。通常は、最も内側のタップ可能な要素がイベントを処理します。

パフォーマンスの問題

onPress を頻繁に使うことで、アプリの動作が重くなる。

考えられる原因と解決策

  • 原因A: onPress ハンドラ内で重い処理を実行している。
    • 説明
      onPress が呼び出されるたびに、UIスレッドをブロックするような非常に時間のかかる計算やネットワークリクエストを行っている場合、アプリがフリーズしたり、カクついたりすることがあります。
    • 解決策
      • onPress 内の処理は、できるだけ軽量に保つようにします。
      • 時間のかかる処理は、非同期的に(async/await を使用して)実行し、UIスレッドをブロックしないようにします。
      • ユーザーエクスペリエンス向上のため、処理中にローディングインジケーターを表示するなど、適切なフィードバックを提供します。
  • 公式ドキュメントを参照する
    React Nativeの公式ドキュメントは常に最新の情報源です。
  • シミュレーター/実機でのテスト
    エミュレーターと実機では挙動が異なる場合があります。両方でテストして問題が再現するか確認します。
  • コードの簡素化
    問題の原因を特定するために、問題の Text コンポーネントとその onPress 関連のコードを最小限の構成にしてテストしてみます。
  • React Native Debuggerを活用する
    • 「Elements」タブで、Text コンポーネントの実際のサイズや位置、スタイルがどうなっているかを確認します。
    • 「Network」タブで、タップ時に何かネットワークリクエストが発火しているかを確認します。
  • ログ出力(console.log)を使用する
    onPress 関数が本当に呼び出されているかを確認するために、関数の先頭で console.log('Text pressed!') などを出力してみてください。


Text#onPress は、テキストをタップ可能にするための非常に便利なプロパティです。ここでは、いくつかの一般的な使用例と、それぞれのコードのポイントを説明します。

例1: シンプルなテキストのタップイベント

最も基本的な使い方です。テキストをタップすると、アラートが表示されます。

import React from 'react';
import { View, Text, Alert, StyleSheet } from 'react-native';

const SimpleTapText = () => {
  // テキストがタップされたときに実行される関数
  const handleTextPress = () => {
    Alert.alert('お知らせ', 'テキストがタップされました!');
  };

  return (
    <View style={styles.container}>
      {/* onPress プロパティに実行したい関数を渡す */}
      <Text onPress={handleTextPress} style={styles.tapText}>
        このテキストをタップしてください
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
  },
  tapText: {
    fontSize: 20,
    color: 'blue',
    padding: 15, // タップしやすいようにパディングを追加
    backgroundColor: '#e0e0ff',
    borderRadius: 8,
    overflow: 'hidden', // Androidでの背景色表示のために必要になることがある
  },
});

export default SimpleTapText;

解説

  • padding を追加することで、タップ可能な領域が視覚的にも広がり、ユーザーにとってタップしやすくなります。
  • <Text onPress={handleTextPress}> のように、onPress プロパティにこの関数を渡すことで、テキストがタップされたときに handleTextPress が実行されます。
  • handleTextPress という関数を定義し、その中で Alert.alert を呼び出しています。

例2: アロー関数を直接 onPress に渡す

簡単な処理であれば、onPress プロパティに直接アロー関数を記述することもできます。

import React from 'react';
import { View, Text, Alert, StyleSheet } from 'react-native';

const InlineTapText = () => {
  return (
    <View style={styles.container}>
      {/* onPress に直接アロー関数を記述 */}
      <Text
        onPress={() => Alert.alert('確認', 'インライン関数が実行されました。')}
        style={styles.inlineText}
      >
        このテキストもタップ可能
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#eafafa',
  },
  inlineText: {
    fontSize: 18,
    color: 'green',
    textDecorationLine: 'underline', // リンクのように見せる
    padding: 10,
  },
});

export default InlineTapText;

解説

  • この方法は、イベントハンドラが非常にシンプルな場合や、特定のプロパティ(例: item.id)を引数として渡したい場合に便利です。
  • onPress={() => Alert.alert(...) } のように、onPress の中に直接 Alert.alert を呼び出すアロー関数を書いています。

例3: タップイベントで状態(State)を更新する

React Nativeアプリでは、ユーザーの操作に応じてUIを更新するために State を使うことがよくあります。

import React, { useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';

const StateUpdateText = () => {
  // count というStateを定義し、初期値を0に設定
  const [count, setCount] = useState(0);

  // テキストがタップされたときにcountを1増やす関数
  const incrementCount = () => {
    setCount(prevCount => prevCount + 1); // 以前のStateに基づいて更新
  };

  return (
    <View style={styles.container}>
      <Text style={styles.infoText}>
        タップされた回数: {count}
      </Text>
      <Text onPress={incrementCount} style={styles.counterText}>
        ここをタップしてカウント!
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fffbe0',
  },
  infoText: {
    fontSize: 24,
    marginBottom: 20,
    color: '#333',
  },
  counterText: {
    fontSize: 22,
    color: 'darkorange',
    padding: 20,
    borderWidth: 2,
    borderColor: 'darkorange',
    borderRadius: 10,
    fontWeight: 'bold',
  },
});

export default StateUpdateText;

解説

  • <Text onPress={incrementCount}> で、テキストがタップされるたびに incrementCount が実行され、count の値が更新され、UIが再レンダリングされます。
  • incrementCount 関数内で setCount を呼び出し、count の値を 1 増やしています。
  • useState(0) を使って count という名前のState変数を定義し、初期値を 0 に設定しています。setCountcount を更新するための関数です。

例4: ネストされた Text コンポーネントでの onPress

一つの文章の中で、特定の単語やフレーズだけをタップ可能にしたい場合によく使われます。

import React from 'react';
import { View, Text, Alert, StyleSheet } from 'react-native';

const NestedTapText = () => {
  const handleTermsPress = () => {
    Alert.alert('利用規約', '利用規約のページに移動します。');
  };

  const handlePrivacyPress = () => {
    Alert.alert('プライバシーポリシー', 'プライバシーポリシーのページに移動します。');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.baseText}>
        当社のサービスをご利用になる前に、必ず
        <Text onPress={handleTermsPress} style={styles.linkText}>
          利用規約
        </Text><Text onPress={handlePrivacyPress} style={styles.linkText}>
          プライバシーポリシー
        </Text>
        をご確認ください。
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 20,
    backgroundColor: '#e6ffe6',
  },
  baseText: {
    fontSize: 16,
    lineHeight: 24, // 行の高さを調整して読みやすくする
    textAlign: 'center',
    color: '#333',
  },
  linkText: {
    fontSize: 16, // 親のTextと同じフォントサイズを維持
    color: 'darkblue',
    fontWeight: 'bold',
    textDecorationLine: 'underline', // 下線を表示
  },
});

export default NestedTapText;

解説

  • スタイルも継承されますが、ネストされた <Text> に独自のスタイルを設定して上書きすることも可能です。
  • ネストされた <Text>onPress を設定することで、その部分だけがタップ可能になります。
  • <Text> コンポーネントの中に、別の <Text> コンポーネントをネストすることができます。

例5: TouchableOpacityText の組み合わせ

Text#onPress は便利ですが、タップ可能な領域がテキストの大きさに依存します。より大きなタップ可能な領域を確保したい場合や、タップ時の視覚的なフィードバック(Opacityの変更)が必要な場合は、TouchableOpacity の中に Text を配置するのが一般的です。

import React from 'react';
import { View, Text, TouchableOpacity, Alert, StyleSheet } from 'react-native';

const TouchableText = () => {
  const handleButtonPress = () => {
    Alert.alert('アクション', 'ボタンのようにタップされました!');
  };

  return (
    <View style={styles.container}>
      {/* Text#onPress の代わりに TouchableOpacity を使用 */}
      <TouchableOpacity onPress={handleButtonPress} style={styles.button}>
        <Text style={styles.buttonText}>
          タップできる領域が広いボタン
        </Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5dc',
  },
  button: {
    backgroundColor: '#8a2be2', // 紫色
    paddingVertical: 15,
    paddingHorizontal: 30,
    borderRadius: 25,
    elevation: 3, // Androidの影
    shadowColor: '#000', // iOSの影
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
  buttonText: {
    color: 'white',
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});

export default TouchableText;
  • ボタンのような見た目や挙動を実現したい場合に非常に適しています。
  • TouchableOpacity 自体に onPress を設定し、その中に Text を含めることで、Text の実際の大きさに関わらず、TouchableOpacity で定義された領域全体がタップ可能になります。
  • <TouchableOpacity> は、タップ時に透明度(opacity)が変化する視覚的なフィードバックを提供します。


React Native Text#onPress の代替方法

<TouchableOpacity> を使用する

最も一般的で推奨される代替方法です。テキストを <TouchableOpacity> で囲むことで、タップ可能な領域を広げ、タップ時に透明度が変化する視覚的なフィードバックを提供します。

コード例

import React from 'react';
import { View, Text, TouchableOpacity, Alert, StyleSheet } from 'react-native';

const TouchableOpacityExample = () => {
  const handlePress = () => {
    Alert.alert('アクション', 'TouchableOpacity がタップされました!');
  };

  return (
    <View style={styles.container}>
      {/* Text を TouchableOpacity で囲む */}
      <TouchableOpacity onPress={handlePress} style={styles.button}>
        <Text style={styles.buttonText}>
          広い領域でタップできるテキスト
        </Text>
      </TouchableOpacity>

      <Text style={{ marginTop: 20 }}>
        ※こちらは通常の
        <Text onPress={() => Alert.alert('補足', 'Text#onPressです')} style={{ color: 'blue', textDecorationLine: 'underline' }}>
          Text#onPress
        </Text>
        の例
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f8f8f8',
  },
  button: {
    backgroundColor: '#6200EE', // マテリアルデザインのプライマリカラー
    paddingVertical: 15,
    paddingHorizontal: 30,
    borderRadius: 8,
    elevation: 4, // Android の影
    shadowColor: '#000', // iOS の影
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
  buttonText: {
    color: 'white',
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});

export default TouchableOpacityExample;

利点

  • 汎用性
    ボタンやカードなど、さまざまなUI要素でインタラクションを追加するのに使われます。
  • 視覚的フィードバック
    タップ時に透明度(opacity)が自然に変化するため、ユーザーに「タップできる」という感覚を与えやすいです。
  • 広いタップ領域
    paddingmargin を使って、テキストの内容に関わらずタップ可能な領域を自由に設定できます。

欠点

  • ネストされた <Text>
    一部のテキストだけをタップ可能にする場合(例:文章中の特定の単語だけをリンクにする)は、Text#onPress の方がシンプルになることがあります。
  • テキスト以外の要素もタップ可能になる
    Text 以外の要素(例えばアイコンなど)も一緒に <TouchableOpacity> 内に配置すると、それらもタップイベントの対象になります。

<Pressable> を使用する (React Native 0.63 以降推奨)

<Pressable> は、TouchableOpacityTouchableWithoutFeedback などの古い Touchable コンポーネントに代わる、より柔軟で高機能なコンポーネントです。より細かいタップ状態(押されている状態、押されていない状態など)に応じたスタイリングや、より詳細なイベントハンドリングが可能です。

コード例

import React, { useState } from 'react';
import { View, Text, Pressable, Alert, StyleSheet } from 'react-native';

const PressableExample = () => {
  const [pressCount, setPressCount] = useState(0);

  const handlePress = () => {
    Alert.alert('Pressable', 'Pressable がタップされました!');
    setPressCount(prev => prev + 1);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.infoText}>
        タップされた回数: {pressCount}
      </Text>
      {/* Text を Pressable で囲む */}
      <Pressable
        onPress={handlePress}
        // 押されている状態に応じたスタイルを動的に適用
        style={({ pressed }) => [
          styles.pressableButton,
          pressed ? styles.buttonPressed : styles.buttonReleased,
        ]}
      >
        <Text style={styles.pressableText}>
          Pressable でタップ
        </Text>
      </Pressable>

      <Text style={{ marginTop: 20 }}>
        追加情報: {'\n'}
        <Pressable
          onPress={() => Alert.alert('ロングプレス', '長押しイベント!')}
          onLongPress={() => Alert.alert('長押し', '長押ししました!')} // 長押しイベント
          delayLongPress={500} // 長押しと認識するまでの時間(ミリ秒)
          style={({ pressed }) => [
            styles.inlinePressable,
            pressed ? styles.inlinePressed : {},
          ]}
        >
          <Text style={styles.inlinePressableText}>
            長押しできるテキスト
          </Text>
        </Pressable>
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#e6ffe6',
    padding: 20,
  },
  infoText: {
    fontSize: 20,
    marginBottom: 20,
    color: '#333',
  },
  pressableButton: {
    paddingVertical: 15,
    paddingHorizontal: 30,
    borderRadius: 10,
    alignItems: 'center',
    justifyContent: 'center',
    minWidth: 200,
  },
  buttonPressed: {
    backgroundColor: '#4CAF50', // 押された時の色 (緑)
  },
  buttonReleased: {
    backgroundColor: '#8BC34A', // 通常時の色 (薄い緑)
  },
  pressableText: {
    color: 'white',
    fontSize: 18,
    fontWeight: 'bold',
  },
  inlinePressable: {
    padding: 5,
    borderRadius: 5,
  },
  inlinePressed: {
    backgroundColor: 'rgba(0, 0, 255, 0.1)', // 青の半透明
  },
  inlinePressableText: {
    color: 'blue',
    textDecorationLine: 'underline',
    fontSize: 16,
  },
});

export default PressableExample;

利点

  • 汎用性
    TouchableOpacity が提供する機能の多くをカバーしつつ、さらに高度なカスタマイズが可能です。
  • 細かい制御
    タップ遅延時間 (delayLongPress) などの詳細な設定が可能です。
  • 動的なスタイリング
    style プロパティに関数を渡すことで、pressed (押されているか) などの状態に基づいてスタイルを動的に変更できます。これにより、よりリッチな視覚的フィードバックを実現できます。
  • 豊富なイベントハンドラ
    onPress, onLongPress, onPressIn, onPressOut など、タップのさまざまな段階に対応したイベントを処理できます。

欠点

  • 古いRNバージョンとの互換性
    React Native 0.63 以降で導入されたため、それ以前のバージョンを使用している場合は利用できません。
  • 学習コスト
    TouchableOpacity に比べて提供される機能が多いため、少し複雑に感じるかもしれません。しかし、その分柔軟性も高まります。

<TouchableWithoutFeedback> を使用する

視覚的なフィードバックを一切提供せずに、タップイベントのみを処理したい場合に利用します。

コード例

import React from 'react';
import { View, Text, TouchableWithoutFeedback, Alert, StyleSheet } from 'react-native';

const TouchableWithoutFeedbackExample = () => {
  const handlePress = () => {
    Alert.alert('情報', 'フィードバックなしでタップされました。');
  };

  return (
    <View style={styles.container}>
      {/* Text を TouchableWithoutFeedback で囲む */}
      <TouchableWithoutFeedback onPress={handlePress}>
        <View style={styles.innerView}>
          <Text style={styles.text}>
            フィードバックなしでタップ
          </Text>
        </View>
      </TouchableWithoutFeedback>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f8ff',
  },
  innerView: {
    padding: 20,
    backgroundColor: '#add8e6', // 背景色でタップ領域を視覚的に示す
    borderRadius: 10,
  },
  text: {
    fontSize: 18,
    color: '#333',
  },
});

export default TouchableWithoutFeedbackExample;

利点

  • シンプルなタップイベント
    単純にタップイベントを検出したいだけの用途に向いています。
  • 視覚的フィードバックなし
    タップ時に要素の見た目を一切変えたくない場合に最適です。
  • タップ領域
    TouchableOpacity と同様に、内部に View などでラップして padding を与えることでタップ領域を広げられます。
  • ユーザー体験
    視覚的なフィードバックがないため、ユーザーが「タップできた」と認識しにくい場合があります。インタラクティブな要素には、何らかのフィードバックを与えることがUI/UXのベストプラクティスです。
  • 文章中のごく一部のテキストのみをタップ可能にする場合
    シンプルな Text#onPress が最も手軽で読みやすいコードになることが多いです。ただし、この場合もタップ領域が狭いという制約はあります。
  • 本当に視覚的なフィードバックが不要で、単にイベントを捕捉したいだけの場合
    <TouchableWithoutFeedback> を検討します。ただし、ユーザー体験には注意が必要です。
  • より高度なインタラクションや細かい状態制御が必要な場合
    <Pressable> を選びましょう。特に React Native 0.63 以降を使用している場合は、これが推奨されます。
  • ほとんどの場合
    <TouchableOpacity> が最適です。視覚的なフィードバックがあり、タップ領域を広げやすいというバランスの取れた利点があります。