🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

前言

辛苦了。
這次的任務中,我們開發了一款名為「Study Spot Vancouver」的自習空間搜尋應用程式。
使用了 React、TypeScript、Supabase、Google Maps API 與 Chakra UI,
實現了在地圖上顯示釘子 → 依條件篩選 → 可跳轉至詳細頁面的機制。

在這個專案中,我能夠全面體驗 API 整合、狀態管理、UI 設計的流程,
並深入理解「地圖應用程式運作的機制」,這是一個很好的機會。

應用程式創建原因

  • 解決個人課題
    在尋找可以自習的地方時,
    Google Maps 只能提供「咖啡廳」「圖書館」等大概的分類。

然而,實際上自習時所需的重要資訊,如靜音、是否有電源、是否有 Wi-Fi 等,
都是當地才能了解的資訊。

尤其是,針對英語朗讀或簡報練習等「可以出聲學習的場所」,幾乎沒有資訊可供參考,每次都需要實地確認。

為了解決這個不便,我決定製作一款「可以依自習條件搜尋的地圖應用程式」。

應用程式概述

GitHub 倉庫:
https://github.com/kazukashima/kadai5.git

這款應用程式將 Vancouver 市內的自習空間顯示在地圖上,
便於透過 Wi-Fi、電源、聲音等條件進行快速篩選。

此外,我自訂了以下 MVP,並依照此進行實作:

  • MVP1 建立了 React + TypeScript + Vite 的開發環境,並部署至 Firebase Hosting,透過 make deploy 進行自動化。
  • MVP2 使用 GitHub Actions 建立 CI/CD,在 push 時自動執行測試與部署。
  • MVP3 導入 Google Maps API,並將從 Supabase 獲取的數據顯示為地圖上的釘子。
  • MVP4 實現可以根據 Wi-Fi / 電源 / 聲音狀態篩選的功能。
  • MVP5 點擊釘子可跳轉至詳細頁面,顯示照片、地址與營業時間並設置可在 Google Maps 打開的連結。

主畫面

スクリーンショット 2025-10-28 002647.png

地圖顯示

透過左上角的 WiFi、電源、聲音按鈕切換,
可依據每個空間是否能使用 Wi-Fi、是否有電源及是否可以小聲交談進行條件篩選。
スクリーンショット 2025-10-28 002811.png

地圖操作示範

點擊地圖上的釘子時,
會彈出顯示設施名稱及「WiFi、電源、聲音狀態」等基本資訊。
按下「查看詳細」按鈕後,
可跳轉至該空間的詳細頁面,確認地址和照片等資訊。
在詳細頁面的「打開」連結中,
可實際打開 Google 地圖進行路徑搜尋或周邊確認。
Map Demo

數據收集方法

自習空間的資訊皆是親自前往確認的。
例如,「是否有 WiFi」、「是否有電源」、「是否可以出聲學習」等在網上無法得知的訊息,
都必須親自到現場詢問工作人員,
或自己學習以確認氛圍。

對於無法前往的設施,我會透過電子郵件進行詢問,
努力獲取準確的資訊。

使用技術

分類 使用技術 / 內容
前端 React + TypeScript + Vite
UI函式庫 Chakra UI(切換按鈕、響應式設計)
資料庫 Supabase(雲端管理自習空間資訊)
地圖繪製 使用 Google Maps API(@vis.gl/react-google-maps)顯示釘子
部署 Firebase Hosting(自動反映至正式環境)
CI/CD GitHub Actions(在 push 時進行測試與自動部署)
自動化 Makefile(透過 make deploy / make test 簡易執行)

架構圖

image.png


開發中遇到的難點與解決方案

1. Google Maps API 與 React 的重新渲染問題

即使發生 React 的重新渲染,Google Maps 的顯示卻無法更新,
即使切換篩選條件,釘子也不會改變。

原因在於 React 的 Virtual DOM 與 Google Maps 的繪製是不同系統獨立運行的。
作為解決方案,採取 key={JSON.stringify(filters)} 的方式進行重新繪製。

<Map key={JSON.stringify(filters)} ...>

2. 篩選的狀態管理(boolean 型別的處理)

在切換三個條件(WiFi、電源、聲音狀態)時,
透過 useState 進行統一管理,並動態更新。

const [filters, setFilters] = useState({
  wifi: false,
  power: false,
  talking: false,
});

每次按下按鈕時,只透過 toggleFilters 反轉特定鍵的值,
如此可簡潔地切換多個條件。

3. 詳細頁面跳轉與 Google 地圖連結生成

在地圖中點擊釘子時,可以跳轉至詳細頁面,並在該頁面動態生成「在 Google 地圖打開」的連結。

<a
  href={`https://www.google.com/maps?q=${spot.latitude},${spot.longitude}`}
  target="_blank"
  rel="noopener noreferrer"
>
  在 Google 地圖打開
</a>

透過模板字串(...),學會了如何動態從緯度與經度組建連結。

成長的點與學習

1. 增強了與外部 API 的整合能力

實際體驗將 Google Maps API 和 Supabase 等外部服務整合進自己的應用程式的流程。
對 API 金鑰管理、非同步處理和環境變數的理解都是一次重大的收穫。

2. 能夠意識到資料結構的設計

透過將 Supabase 的表格設計(id, name, latitude, longitude, wifi, power, talking)與 UI 的運作結合思考,
使我更能意識到資料與 UI 的關聯性。

3. 理解狀態與繪製之間的關係

在篩選切換時釘子無法更新的問題中,
我學會了 React 的重新渲染與外部庫(如 Google Maps)的繪製是獨立運行的。


感想與結語

尚有 UI/UX 改善以及向 Supabase 添加資料等課題存在。
不過,透過自我設計 MVP 並逐步完成應用程式的經驗,
我覺得自己培養了「有目的地進行開發的能力」。

未來我希望進一步增加資料,改善 UI/UX,
將應用程式發展成「實際提供價值的應用程式」。


JISOU 正在招募夥伴!
在日本一流的輸出社群中,你也想一起成長嗎?
https://projisou.jp/


原文出處:https://qiita.com/kazutorahattori/items/b79304ceafae157ba86c


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝22   💬4   ❤️6
675
🥈
我愛JS
📝1   💬4   ❤️2
45
🥉
酷豪
1
#5
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付