1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【アプリ作成】React学んで1ヶ月、デジタル名刺アプリを作ったお話

Posted at

はじめに

こんにちは、Halです。

React・TypeScriptの学習を開始して約1ヶ月半、個人開発としてデジタル名刺アプリを作成しました。

本記事では、以下の内容をまとめています:

  • アプリの機能紹介
  • 使用した技術スタック
  • 開発で苦戦したポイントと解決方法

初学者の視点から、実装の過程で得た学びを共有できればと思います。

今回作成したもの

オンライン・オフラインで、名刺の表示や検索、登録ができるデジタル名刺アプリをテーマに、フロントエンド・バックエンドの構築を行いました。

作成したアプリの機能説明に移りたいと思います。

名刺の検索

トップページからユーザー名で名刺を検索できます。

検索の流れ:

  1. トップページでユーザー名を入力
  2. 検索ボタンをクリック
  3. 該当する名刺ページへ遷移

ユーザー名を入力すると...
名刺検索のデモ

名刺の表示

検索結果として、以下の情報が表示されます:

表示項目:

  • ユーザー名
  • 自己紹介文
  • 好きな技術
  • SNSリンク(X / Qiita / GitHub)

表示モード:

  • ライトモード・ダークモードの切り替えに対応
名刺画面ライトモード 名刺画面ダークモード

名刺の登録

お次は、名刺を新規で登録する機能です。必須項目は名前,自己紹介,好きな技術の3つあります。任意項目はSNSアカウントのID入力です。IDを入力すると、名刺画面で先程のようにリンクボタンが表示されます。

名刺の登録をする
名刺登録のデモ

カスタムスタイリング機能

自己紹介欄ではHTMLタグを使用したスタイリングが可能です。
HTML文字列へのサニタイズ処理を入れていないため、悪意あるスクリプトを仕込まれるとXSSの危険性が潜んでいます。対策については、今後の学習課題として取り組んでいこうと思います

Qiitaの部分を緑文字にした例:
カスタムスタイリング例

使用した技術スタック

このデジタル名刺アプリは次の技術スタックを利用して作成しました。フロントエンドフレームワークで調べるとNext.jsがヒットしますが、今回のようなミニマムなアプリを作るケースは大体vite+React+TanStack Routerで解決できると思います。僕のようなReact学びはじめの初学者はこの構成がおすすめだと思います。

フロントエンド : React
ルーティング : TanStack Router
状態管理 : TanStack Query
UI : Chakra UI
フォーム : React Hoo
k Form
データベース : Supabase
テスト : Vitest & React Testing Library

振り返り

中間テーブルを使ったデータ取得に苦戦

今回、Userテーブルの情報を利用して、中間テーブルを介したskillsテーブルのデータ取得を行う必要がありました。 Supabaseのダッシュボード側からテストユーザーを登録したところ、テストユーザーの名刺が表示されないエラーが発生しました。

▼ 発生したエラーコード

{
  code: 'PGRST116',
  details: 'The result contains 0 rows',
  hint: null,
  message: 'Cannot coerce the result to a single JSON object'
}

テストユーザーを登録時、スキル情報の紐づけを忘れていたことで、内部結合時にnullが返却されていたことが原因でした。内部結合は結合先にレコードが存在しない場合、検索結果から除外されnullになります。同時に、single()メソッドを使用して1件のレコードを期待していたためPGRT116エラーがthrowされたという流れです。

データ取得コード
const { data, error } = await supabase
    .from("users")
    .select(`*,
      user_skill!inner (
        skills (
          skill_id,
          name
        )
      )
    `)
    .eq("user_id", Number(id))
    .single();

解決方法として、!innerを外し、外部結合に変更してフロントエンド側ではスキルデータがない場合何も表示しないようにしました。

エラーを通して内部結合、外部結合の仕様を学ぶ良い機会となりました。

決まった時間にDBのレコード削除 (Cron Job)

今回初めてGitHub ActionsのCron Jobを設定し、決まった時間に昨日登録されたユーザー情報を削除するようにしました。
GitHub ActionsはUTCで動作するため、日本時間との時差(9時間)を考慮する必要がありました。また、本当に削除できているかをテストする際、毎朝6時まで待機するのではなく、workflow_dispatchを設定することで手動実行もできるようにしました。

処理の概要

  • 毎日午前6時(JST)に実行
  • 前日に登録されたレコードを検索、ヒットしたレコードだけ削除

終わりに

以上が今回作成したものになります。技術的な難易度としては低い方だと思いますが、学んだ過程・作成したものをQiitaに投稿することでメリハリのついた学習体験をできたと感じています。

今までは何か新しいことを勉強する場合、コードを動かして得られた結果や、実施した内容もまとめずそのまま放置していました。そうした学び方のせいで数日後には勉強した実感や何かできるようになった達成感もなく、虚無感だけが残るものでした。

今回はQiitaへの記事投稿によって、自分の学んだことやエラーなどの対処を投稿履歴上で追うことができるため、後で振り返りをした際に自分の成長が実感できて良かったです。

今後も、このQiita投稿の習慣はやめずに続けていこうと思います!

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?