
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教育やプログラミング・マーケティング授業も手がける。
公開中のリスキリング体験授業・学習教材
リスキリングに役立つ学習教材や体験授業を公開しています。ご自身の学習にお役立てください。
法律入門 | 民法基礎 総則編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス統計 | 統計調査 統計法規
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス統計 | 統計調査 企画・設計
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
Python 3 エンジニア認定基礎試験 | 基礎講座 初級編 前編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
Python 3 エンジニア認定基礎試験 | 基礎講座 初級編 中編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎 シグマ編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎 分散編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎 相関編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎 回帰分析編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
データサイエンス入門 | 統計基礎 確率分布編
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
プログラミング体験 | マインクラフト
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
Webデザイン体験授業 | LP制作体験
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
Webデザイン入門 | 自己紹介サイト制作体験
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
Unityゲームプログラミング体験
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
プログラミング体験授業 | カレンダー制作
●開催:オンラインまたはオフライン
●会場:福岡市 NPO・ボランティア交流センター(福岡県福岡市中央区今泉1丁目19−22 西鉄天神クラス 4階)
2015年
創業
120名
従業員数
2.3M
月間UU
1,800戸
管理戸数
