React Native Course
Fundamentals

ボタン操作で変わる表示を useState で実装し、「画面上の数字 → state → setXxx」の読み方を練習する第2話です。

useState で画面を動かす - 変わる値を、画面から辿る

第1話 では、画面に出ている固定の文言からファイルと部品を辿る練習をしました。今回は、ボタンを押すたびに変わる表示を追います。

カウンターのように数字が増える画面を見たとき、「この値はコードのどこで持っているのか」と感じたことはないでしょうか。第2話では useState でその仕組みを実装し、表示値 → state → setXxx → onPress の順で読む練習をします。

この記事で扱うこと

実装(A)読み解き(B)
useState 最小例カウンター(+1 ボタン)画面上の数字を {count} から辿る
つまずきやすい点直接代入の回避変わらない表示の原因を切り分ける
第1話との接続HomeScreen への足し方Navigation 内でも同じ読み方
まとめ次に進む順番第3話への導線

1. useState の最小例

第1話で作った Expo プロジェクト、または新規に bunx create-expo-app@latest で作ったプロジェクトを使います。ここでは 1 画面・1 ファイル に絞り、Navigation は触りません。

エントリファイル(App.tsxapp/index.tsx など、プロジェクト構成によります)を次の内容に差し替えてください。

import { useState } from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";

export default function CounterScreen() {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.container}>
      <Text style={styles.count}>{count}</Text>
      <Pressable style={styles.button} onPress={() => setCount(count + 1)}>
        <Text style={styles.buttonLabel}>+1</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    gap: 16,
  },
  count: {
    fontSize: 48,
    fontWeight: "600",
  },
  button: {
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8,
    backgroundColor: "#e2e8f0",
  },
  buttonLabel: {
    fontSize: 16,
    fontWeight: "600",
  },
});

bunx expo start で起動し、+1 を押すたびに中央の数字が増えれば成功です。

ポイントは次の 3 つです。

  • useState(0)いまの値count)と 更新用関数setCount)を受け取る
  • 画面に見える数字は {count} で表示する
  • ボタンが押されたら setCount(count + 1) で値を更新する

2. 読み解きの練習:変わる値を辿る

第1話と同じ型で、いま画面に見えているものから入ります。今回は固定の文言ではなく、押すたびに変わる数字を選びます。

  1. 画面中央の数字(0, 1, 2 …)に注目する
  2. エディタで {count} を探し、どの <Text> に書いてあるか確認する
  3. count の宣言を遡り、const [count, setCount] = useState(0) を見つける
  4. +1 ボタンの onPress から setCount を辿る

流れを言葉にすると、こうなります。

ボタンを押す → setCount が呼ばれる → count が更新される → コンポーネントが再描画される → 画面の数字が変わる

AI 生成コードや他人のコードを読むときも、この順番が使えます。

読み解きの順番探すもの
1変わっている表示(数字・文言・ON/OFF など)
2JSX の {変数名}
3useState の宣言
4setXxx を呼んでいる onPressuseEffect

3. つまずきやすい点

ボタンを押しても数字が変わらない

よくあるのは、count に直接代入してしまうパターンです。

// ❌ 再描画が起きない
onPress={() => {
  count = count + 1;
}}

React では、表示を変えるときは 必ず setCount 経由 で更新します。

// ✅
onPress={() => setCount(count + 1)}

初期表示が想定と違う

useState(0)0 が初期値です。文字列を表示したいなら useState("")、真偽値なら useState(false) のように、最初に画面に出したい値を渡します。

複数の値を同時に変えたい

ラベルと数字を別々に持ちたいときは、state を分けます。

const [count, setCount] = useState(0);
const [label, setLabel] = useState("回数");

第2話では 1 つの state に絞る と読み解きの練習がしやすいです。複数画面で同じ値を共有したい場合は Context や Zustand など別の仕組みになりますが、ここでは扱いません。

4. 第1話との接続例

第1話で React Navigation の HomeScreen を作っている場合、カウンター UI をその中に足せます。読み方は単一画面のときと同じです。

function HomeScreen() {
  const [count, setCount] = useState(0);

  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>Home</Text>
      <Text style={{ fontSize: 32, marginVertical: 12 }}>{count}</Text>
      <Pressable onPress={() => setCount(count + 1)}>
        <Text>+1</Text>
      </Pressable>
    </View>
  );
}

画面が HomeDetail に分かれていても、変わる数字 → {count}useStatesetCount の辿り方は変わりません。Navigation は「どの画面を見せるか」、useState は「その画面の中の値」という役割分担です。

5. まとめ

実装の順番

  1. useState で表示用の値を持つ
  2. JSX で {変数名} として表示する
  3. onPress などから setXxx だけで更新する

読み解きの順番

  1. 変わっている表示を選ぶ
  2. JSX の {変数名} を探す
  3. useStatesetXxx を辿る

ここまでできれば、画面に動きを足す土台ができています。