Reskilling ❘ Programming

iphoneアプリを作ろう!カレンダー編

#リスキリング #レジリエンス #ICT教育 #ITスキル #プログラミング

iphoneアプリを作ろう!
カレンダー編

みなさんが使っているスマートフォンのアプリ。

おしゃれなデザインや便利な機能など様々ありますね。

このようなアプリはどのように作るのでしょうか?

今回は実際にカレンダーアプリを作りながら学んでみましょう!

  • 2015年

    創業

  • 120名

    従業員数

  • 2.3M

    月間UU

  • 1,800戸

    管理戸数

Expo Snackでカレンダーアプリを作ろう

このワークショップでは、Expo Snackを使って、スマートフォンで動く簡単なカレンダーアプリを作ります。

今回は、プログラミング初心者でも進められるように、「コードを書く → 画面を見る → 少し機能を追加する」という流れで進めます。

すべてを理解してから進む必要はありません。

まずはコードを入力して動かしてみて、「このコードを書くと、こういう画面になるんだ」という感覚をつかんでいきましょう。

この授業で作るもの

最終的には、次のような機能を持つカレンダーを作ります。

  • カレンダーのタイトルを表示

  • 年月を表示

  • 日曜日〜土曜日を表示

  • 日付をカレンダー状に並べる

  • 「‹」「›」ボタンで前月・次月に移動

  • スマートフォンで見やすいようにデザインする

今日の進め方

各ステップでは、次の流れで進めます。

① 説明を聞く → ② コードを入力する → ③ Expo Snackで実行する → ④ 画面を確認する

もし自分で入力してうまく動かなかった場合は、そのステップの完成コードをそのままコピーしてOKです。

大切なのは、完璧にコードを入力することではなく、

「コードを変更すると、スマホの画面が変わる」

という体験をすることです。


Step 1 まず文字を表示してみよう

最初は、とても簡単なところから始めます。

スマートフォンの画面に、

「カレンダーアプリ」

と表示してみましょう。

まず、Expo Snackに以下のコードを入力してください。

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

export default function App() {
  return (
    <View>
      <Text>カレンダーアプリ</Text>
    </View>
  );
}

コードを入力したら、Expo Snackのプレビューを確認します。

「カレンダーアプリ」と表示されていれば成功です。

Appって何?

function App() {

これはJavaScriptの関数です。

JavaScriptを使ったことがある人なら、

function hello() {
  // 処理
}

のような関数を見たことがあると思います。

Reactでは、この関数を使ってスマートフォンの画面を作ります。

つまり、まずは、

Appという関数が、アプリの画面を作っている

と考えてください。

returnって何?

return (
  <View>
    <Text>カレンダーアプリ</Text>
  </View>
);

returnはJavaScriptでも使いますね。

Reactでは、このreturnの中に、

「画面に表示したいもの」

を書きます。

ViewとText

<View>
  <Text>カレンダーアプリ</Text>
</View>

React Nativeには、スマートフォンの画面を作るための部品が用意されています。

Viewは画面の箱、Textは文字を表示するための部品、と考えると分かりやすいです。

今回は、

View
 └─ Text
      └─ カレンダーアプリ

という構造になっています。


Step 2 画面を少しデザインする

次は、さきほど表示した文字を少し大きくして、画面の中央に置いてみましょう。

今度は、以下のコードに置き換えてください。

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

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダーアプリ</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
  },
});

プレビューを見ると、文字が中央に移動して、大きくなったと思います。

styleとは?

ここで、

<View style={styles.container}>

という書き方が出てきました。

これは、

「このViewには、このデザインを適用してください」

という意味です。

Webサイトを作ったことがあれば、CSSをイメージすると分かりやすいです。

stylesとは?

コードの下の方を見ると、

const styles = StyleSheet.create({

があります。

ここに画面のデザインを書いています。

例えば、

title: {
  fontSize: 28,
  fontWeight: 'bold',
},

は、

文字を28くらいの大きさにして、太字にする

という設定です。

React Nativeでは、WebのCSSと似た考え方でデザインできます。


Step 3 現在の年月を表示する

次は、カレンダーに「何年何月なのか」を表示します。

例えば、

カレンダー

2026年 10月

のような表示です。

JavaScriptには、現在の日付を取得するためのDateがあります。

以下のコードに置き換えてください。

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

export default function App() {
  const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth() + 1;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダー</Text>

      <Text style={styles.month}>
        {year}年 {month}月
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 30,
    paddingTop: 70,
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 25,
  },

  month: {
    fontSize: 20,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});

プレビューを確認すると、現在の年月が表示されます。

DateはJavaScriptの機能

ここはReact特有のものではありません。

const date = new Date();

は、JavaScriptで現在の日付を取得しています。

const year = date.getFullYear();

で「年」を取得します。

const month = date.getMonth() + 1;

で「月」を取得します。

ここで少し注意があります。

JavaScriptのgetMonth()は、1月を0として数えます。

そのため、

getMonth() + 1

としています。

{}の中にはJavaScriptを書ける

ここがReactで重要なポイントです。

<Text style={styles.month}>
  {year}年 {month}月
</Text>

{}の中にJavaScriptを書くことができます。

例えば、

<Text>{year}</Text>

なら、yearの中身が表示されます。

PHPを知っている人なら、

<?= $year ?>

のようなイメージで考えると分かりやすいです。


Step 4 曜日を表示する

次は、カレンダーの上に曜日を表示します。

日 月 火 水 木 金 土

という部分です。

以下のコードに置き換えてください。

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

export default function App() {
  const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth() + 1;

  const week = ['日', '月', '火', '水', '木', '金', '土'];

  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダー</Text>

      <Text style={styles.month}>
        {year}年 {month}月
      </Text>

      <View style={styles.week}>
        {week.map(day => (
          <Text style={styles.weekText} key={day}>
            {day}
          </Text>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 30,
    paddingTop: 70,
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 25,
  },

  month: {
    fontSize: 20,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 20,
  },

  week: {
    flexDirection: 'row',
  },

  weekText: {
    width: '14.28%',
    textAlign: 'center',
    fontWeight: 'bold',
    padding: 10,
  },
});

配列を作る

まず、

const week = ['日', '月', '火', '水', '木', '金', '土'];

があります。

これはJavaScriptの普通の配列です。

中には7個の文字が入っています。

日
月
火
水
木
金
土

map()で1個ずつ表示する

次に、

{week.map(day => (
  <Text style={styles.weekText} key={day}>
    {day}
  </Text>
))}

が出てきます。

ここでmap()を使っています。

JavaScriptのmap()を知っている人なら、

配列の中身を1個ずつ取り出して処理する

と考えればOKです。

今回は、取り出した曜日をTextとして表示しています。

つまり、

日 → Textにする
月 → Textにする
火 → Textにする
...
土 → Textにする

という処理をしています。


Step 5 カレンダーの日付を作る

いよいよカレンダーらしくなってきます。

次は、

        1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
...

のように、日付を並べます。

以下のコードに置き換えてください。

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

export default function App() {
  const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth();

  const days = new Date(year, month + 1, 0).getDate();
  const start = new Date(year, month, 1).getDay();

  const cells = Array(start).fill('').concat(
    Array.from({ length: days }, (_, i) => i + 1)
  );

  const week = ['日', '月', '火', '水', '木', '金', '土'];

  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダー</Text>

      <Text style={styles.month}>
        {year}年 {month + 1}月
      </Text>

      <View style={styles.week}>
        {week.map(day => (
          <Text style={styles.weekText} key={day}>
            {day}
          </Text>
        ))}
      </View>

      <View style={styles.calendar}>
        {cells.map((day, i) => (
          <View style={styles.cell} key={i}>
            <Text>{day}</Text>
          </View>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 30,
    paddingTop: 70,
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 25,
  },

  month: {
    fontSize: 20,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 20,
  },

  week: {
    flexDirection: 'row',
  },

  weekText: {
    width: '14.28%',
    textAlign: 'center',
    fontWeight: 'bold',
    padding: 10,
  },

  calendar: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },

  cell: {
    width: '14.28%',
    height: 55,
    alignItems: 'center',
    justifyContent: 'center',
    borderWidth: 1,
    borderColor: '#eee',
  },
});

ここは今回の中で一番JavaScriptの処理が多いところです。

ただし、今は全部を理解する必要はありません。

まずは、

「この処理で、その月のカレンダーに必要な日付を作っている」

くらいで大丈夫です。

daysは、その月の日数

const days = new Date(year, month + 1, 0).getDate();

これは、

「この月は何日まである?」

を調べています。

例えば31日ある月なら、

days = 31

となります。

startは、1日が何曜日か

const start = new Date(year, month, 1).getDay();

これは、

「その月の1日は何曜日?」

を調べています。

JavaScriptでは、

日曜日 → 0
月曜日 → 1
火曜日 → 2
...
土曜日 → 6

となります。

cellsはカレンダーに表示するデータ

const cells = Array(start).fill('').concat(
  Array.from({ length: days }, (_, i) => i + 1)
);

ここは少し複雑です。

例えば、月の1日が水曜日だった場合、

日 月 火 水 木 金 土
             1  2  3

となります。

そのため、最初に「空白」を3個用意します。

イメージとしては、

空白 空白 空白 1 2 3 4 5 6 7...

という配列を作っていると思ってください。

その配列を、

cells.map(...)

で1個ずつ画面に表示しています。

flexWrapで折り返す

calendar: {
  flexDirection: 'row',
  flexWrap: 'wrap',
},

flexDirection: 'row'で横方向に並べます。

そして、

flexWrap: 'wrap'

で、横に入りきらなくなったら次の行に折り返します。

その結果、

1  2  3  4  5  6  7
8  9 10 11 12 13 14
15 16 17 18 19 20 21

というカレンダーになります。


Step 6 前月・次月ボタンを作る

ここで、Reactの重要な機能を1つ使います。

**useState**です。

ここまでは「現在の月」を表示していました。

ここからは、

「ボタンを押したら月を変更する」

という機能を追加します。

以下のコードに置き換えてください。

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

export default function App() {
  const [month, setMonth] = useState(new Date());

  const year = month.getFullYear();
  const m = month.getMonth();

  const days = new Date(year, m + 1, 0).getDate();
  const start = new Date(year, m, 1).getDay();

  const cells = Array(start).fill('').concat(
    Array.from({ length: days }, (_, i) => i + 1)
  );

  const week = ['日', '月', '火', '水', '木', '金', '土'];

  const prevMonth = () =>
    setMonth(new Date(year, m - 1, 1));

  const nextMonth = () =>
    setMonth(new Date(year, m + 1, 1));

  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダー</Text>

      <View style={styles.header}>
        <Pressable onPress={prevMonth}>
          <Text style={styles.button}>‹</Text>
        </Pressable>

        <Text style={styles.month}>
          {year}年 {m + 1}月
        </Text>

        <Pressable onPress={nextMonth}>
          <Text style={styles.button}>›</Text>
        </Pressable>
      </View>

      <View style={styles.week}>
        {week.map(day => (
          <Text style={styles.weekText} key={day}>
            {day}
          </Text>
        ))}
      </View>

      <View style={styles.calendar}>
        {cells.map((day, i) => (
          <View style={styles.cell} key={i}>
            <Text>{day}</Text>
          </View>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 30,
    paddingTop: 70,
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 25,
  },

  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 15,
  },

  month: {
    fontSize: 20,
    fontWeight: 'bold',
  },

  button: {
    fontSize: 35,
    paddingHorizontal: 15,
  },

  week: {
    flexDirection: 'row',
  },

  weekText: {
    width: '14.28%',
    textAlign: 'center',
    fontWeight: 'bold',
    padding: 10,
  },

  calendar: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },

  cell: {
    width: '14.28%',
    height: 55,
    alignItems: 'center',
    justifyContent: 'center',
    borderWidth: 1,
    borderColor: '#eee',
  },
});

プレビューで、

‹    2026年10月    ›

のようになっていることを確認してください。

そして›を押してみましょう。

次の月に変われば成功です。

useStateとは?

ここが今回のReact学習で最も重要なところです。

const [month, setMonth] = useState(new Date());

少し難しそうに見えますが、まずは、

month
↓
現在表示している月

setMonth
↓
月を変更するための機能

と覚えてください。

最初は、

month = 現在の月

です。

そして、

setMonth(...)

を使うことで、月を変更できます。

ボタンを押したら何が起こる?

次月ボタンは、

<Pressable onPress={nextMonth}>

となっています。

これは、

「このボタンが押されたらnextMonthを実行する」

という意味です。

そして、

const nextMonth = () =>
  setMonth(new Date(year, m + 1, 1));

で、現在の月の次の月に変更しています。

例えば、

10月
 ↓
11月

という変更です。

前月ボタンは逆に、

const prevMonth = () =>
  setMonth(new Date(year, m - 1, 1));

となっています。

Reactが画面を更新してくれる

ここがReactの大事なところです。

ボタンを押す
 ↓
setMonth()
 ↓
monthが変わる
 ↓
Reactが変化を確認
 ↓
画面を更新

その結果、カレンダー全体が新しい月に変わります。

普通のJavaScriptでは、自分でHTMLを書き換える処理を考えることがあります。

Reactでは、

「データが変わったら、Reactが画面を更新してくれる」

という仕組みになっています。


Step 7 デザインを整えて完成

最後に、見た目を整えます。

ここでは新しい機能を追加するのではなく、これまで作ったカレンダーを少し見やすくします。

以下の完成版コードに置き換えてください。

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

export default function App() {
  const [month, setMonth] = useState(new Date());

  const year = month.getFullYear();
  const m = month.getMonth();

  const days = new Date(year, m + 1, 0).getDate();
  const start = new Date(year, m, 1).getDay();

  const cells = Array(start).fill('').concat(
    Array.from({ length: days }, (_, i) => i + 1)
  );

  const week = ['日', '月', '火', '水', '木', '金', '土'];

  const prevMonth = () =>
    setMonth(new Date(year, m - 1, 1));

  const nextMonth = () =>
    setMonth(new Date(year, m + 1, 1));

  return (
    <View style={styles.container}>
      <Text style={styles.title}>カレンダー</Text>

      <View style={styles.header}>
        <Pressable onPress={prevMonth}>
          <Text style={styles.button}>‹</Text>
        </Pressable>

        <Text style={styles.month}>
          {year}年 {m + 1}月
        </Text>

        <Pressable onPress={nextMonth}>
          <Text style={styles.button}>›</Text>
        </Pressable>
      </View>

      <View style={styles.week}>
        {week.map(day => (
          <Text style={styles.weekText} key={day}>
            {day}
          </Text>
        ))}
      </View>

      <View style={styles.calendar}>
        {cells.map((day, i) => (
          <View style={styles.cell} key={i}>
            <Text style={styles.day}>{day}</Text>
          </View>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 30,
    paddingTop: 70,
    backgroundColor: '#fff',
  },

  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 25,
  },

  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 15,
  },

  month: {
    fontSize: 20,
    fontWeight: 'bold',
  },

  button: {
    fontSize: 35,
    paddingHorizontal: 15,
  },

  week: {
    flexDirection: 'row',
  },

  weekText: {
    width: '14.28%',
    textAlign: 'center',
    fontWeight: 'bold',
    padding: 10,
  },

  calendar: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },

  cell: {
    width: '14.28%',
    height: 55,
    alignItems: 'center',
    justifyContent: 'center',
    borderWidth: 1,
    borderColor: '#eee',
  },

  day: {
    fontSize: 16,
  },
});

これでカレンダーアプリの完成です!

最後に、実際に操作してみましょう。

  • 現在の月が表示されているか

  • 日付が正しく並んでいるか

  • ‹を押すと前の月になるか

  • ›を押すと次の月になるか

  • 前後の月に移動しても、曜日と日付が正しく並ぶか

を確認してください。

今日覚えてほしいこと

今回の授業で、すべてのコードを暗記する必要はありません。

特に覚えてほしいのは、次の5つです。

① Reactでは関数で画面を作る

function App() {
  return (...);
}

② JSXを使って画面を書く

<View>
  <Text>こんにちは</Text>
</View>

③ {}の中にJavaScriptを書ける

<Text>{year}年</Text>

④ map()を使って同じ部品を繰り返し表示できる

{week.map(day => (
  <Text>{day}</Text>
))}

⑤ useStateで、画面に関係するデータを変更できる

const [month, setMonth] = useState(new Date());

そして、Reactを理解するうえで一番大切なのは、

データが変わる
    ↓
Reactが変化を検知
    ↓
画面が更新される

という考え方です。

今回作ったカレンダーも、

month
  ↓
カレンダーの日付を計算
  ↓
画面に表示

という仕組みになっています。

「JavaScriptでデータを作る → Reactで画面に表示する」

この感覚を持てれば、今回のカレンダーから、ToDoアプリやメモ帳、簡単なゲームなどにも発展させていけます。

・本講座の制作
CIT経営開発事務所

・監修
CIT経営開発事務所 代表
井上 隆寛(いのうえ・たかひろ)

事業コンサルタント
AI開発エンジニア
行政書士R6合格者未登録

大手システム開発会社にてフルスタックSE兼Webデザイナーとして従事。2021年にコンサルタントとして独立し、企業に対するITコンサルティング・ソリューション導入支援事業を開始。2023年にはイベント企画・運営事業を新たに展開、2024年には行政書士試験に合格。現在はAIコンサルティング、システム開発、エンターテイメントの3事業を柱に、企業の技術顧問や講師としてICT教育やプログラミング・マーケティング授業も手がける。

公開中のリスキリング体験授業・学習教材

リスキリングに役立つ学習教材や体験授業を公開しています。ご自身の学習にお役立てください。

  • 2015年

    創業

  • 120名

    従業員数

  • 2.3M

    月間UU

  • 1,800戸

    管理戸数