React Native - 第2章:インタラクションとリスト

React Native - ユーザーインタラクションとリスト表示

入力、ボタン、リスト表示の方法を学ぼう

ユーザーインタラクションとリスト表示

ユーザーからの入力を受け取り、リストを表示する方法を学びましょう。


ユーザー入力 - TextInput

React Nativeでテキスト入力を扱うには、TextInputコンポーネントを使います。

基本的な使い方

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

function App() {
  const [text, setText] = useState('');

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        value={text}
        onChangeText={setText}
        placeholder="ここに入力してください"
      />
      <Text>入力された内容: {text}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  input: {
    height: 40,
    borderColor: '#ccc',
    borderWidth: 1,
    paddingHorizontal: 10,
    marginBottom: 10,
  },
});

重要なプロパティ:

  • value: 入力欄の現在の値(stateと連動)
  • onChangeText: テキストが変更された時に呼ばれる関数
  • placeholder: 入力前に表示されるヒントテキスト
  • style: スタイルを適用

ボタン - ButtonとTouchableOpacity

React Nativeには、ユーザーのタップに反応する2つの主要なコンポーネントがあります。

1. Button - シンプルな標準ボタン

Buttonは、最もシンプルなボタンコンポーネントです。

import { View, Button } from 'react-native';

function App() {
  const handlePress = () => {
    console.log('ボタンが押されました');
  };

  return (
    <View>
      <Button 
        title="押してください" 
        onPress={handlePress}
      />
    </View>
  );
}

Buttonの特徴:

メリット

  • シンプルで使いやすい
  • 最小限のコードで実装できる

デメリット

  • デザインのカスタマイズができない
  • プラットフォーム(iOS/Android)によって見た目が異なる

2. TouchableOpacity - カスタマイズ可能

TouchableOpacityは、自由にデザインできるタップ可能なコンポーネントです。

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

function App() {
  const handlePress = () => {
    console.log('カスタムボタンが押されました');
  };

  return (
    <View>
      <TouchableOpacity 
        style={styles.button}
        onPress={handlePress}
      >
        <Text style={styles.buttonText}>カスタムボタン</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#2196F3',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

メリット

  • 完全にカスタマイズ可能
  • タップ時に半透明になるフィードバック効果
  • どんなコンポーネントでもタップ可能にできる

リスト表示 - FlatList

FlatListは、大量のデータを効率的に表示するためのコンポーネントです。

基本的な使い方

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

function App() {
  const fruits = ['りんご', 'バナナ', 'オレンジ', 'ぶどう', 'いちご'];

  return (
    <View style={styles.container}>
      <FlatList
        data={fruits}  // 表示するデータ(配列)
        renderItem={({ item }) => (  // 各アイテムの表示方法
          <View style={styles.item}>
            <Text style={styles.text}>{item}</Text>
          </View>
        )}
        keyExtractor={(item, index) => index.toString()}  // 各アイテムのユニークなキー
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  text: {
    fontSize: 18,
  },
});

必須のプロパティ:

  • data: 表示するデータの配列
  • renderItem: 各アイテムをどう表示するか定義する関数
  • keyExtractor: 各アイテムのユニークなキーを返す関数

オブジェクトの配列を表示

interface User {
  id: number;
  name: string;
  email: string;
}

function UserList() {
  const users: User[] = [
    { id: 1, name: '太郎', email: '[email protected]' },
    { id: 2, name: '花子', email: '[email protected]' },
    { id: 3, name: '次郎', email: '[email protected]' },
  ];

  return (
    <FlatList
      data={users}
      renderItem={({ item }) => (
        <View style={styles.userCard}>
          <Text style={styles.name}>{item.name}</Text>
          <Text style={styles.email}>{item.email}</Text>
        </View>
      )}
      keyExtractor={(item) => item.id.toString()}  // IDをキーに使う
    />
  );
}

ポイント:

  • オブジェクトに一意のIDがある場合、それをkeyExtractorで使う
  • インデックスよりもIDの方が安全

実践例:Todoリスト

import { useState } from 'react';
import { 
  View, 
  Text, 
  TextInput, 
  Button, 
  FlatList, 
  TouchableOpacity,
  StyleSheet 
} from 'react-native';

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

function TodoList() {
  const [input, setInput] = useState('');
  const [todos, setTodos] = useState<Todo[]>([]);

  const addTodo = () => {
    if (input.trim()) {
      setTodos([
        ...todos,
        { id: Date.now(), text: input, completed: false }
      ]);
      setInput('');
    }
  };

  const toggleTodo = (id: number) => {
    setTodos(
      todos.map(todo =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Todoリスト</Text>

      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          value={input}
          onChangeText={setInput}
          placeholder="Todoを入力"
        />
        <Button title="追加" onPress={addTodo} />
      </View>

      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity 
            onPress={() => toggleTodo(item.id)}
            style={styles.todoItem}
          >
            <Text 
              style={[
                styles.todoText,
                item.completed && styles.completed
              ]}
            >
              {item.text}
            </Text>
          </TouchableOpacity>
        )}
        keyExtractor={(item) => item.id.toString()}
        ListEmptyComponent={() => (
          <Text style={styles.empty}>Todoを追加してください</Text>
        )}
      />
    </View>
  );
}

まとめ

TextInput

  • ユーザーからテキスト入力を受け取る
  • valueonChangeTextで制御
  • keyboardType、secureTextEntryなどで動作をカスタマイズ

ボタン

  • Button: シンプルだがカスタマイズ不可
  • TouchableOpacity: 自由にデザイン可能
  • onPressでタップ時の処理を定義

FlatList

  • 大量のデータを効率的に表示
  • datarenderItemkeyExtractorが必須
  • 画面に見えている部分だけレンダリング(パフォーマンスが良い)

これで、ユーザー入力を受け取り、ボタンで操作し、リストで表示する基本的なアプリが作れるようになりました!

次は、これらを組み合わせた実践的なアプリ開発を学びましょう。