【技育CAMP2024】ハッカソン Vol.12に即席チームとして参加してきました!!
今回は制作物やハッカソン中に躓いた点などをまとめていきます。
ランジャニーズ
ランジャニちゃん
最初の制作物の案を出し合っている際に、「旅行したいけど特に行きたい場所がなく、そのまま旅行のタイミングを見失う」といった悩みを持ったメンバーがいたため、今回のハッカソンではその悩みを解決するような作品を作ることにしました。
今回は即席メンバーということで現時点で触ったことのある技術を話し合い、フロントエンドとバックエンドに二人ずつ割り当て開発を進めました。私はフロントエンドを担当し、今まで触ってきたNext.js+TypeScriptを使用することにしました。Webデザインもフロント班の二人で進めることとなり、figmaを使用しました。
座標から現在地を特定しマップに描画するために使用。
バックエンドからランダムに与えられる地名から座標を検索するために使用。ここで取得した座標をGoogle Map APIに渡しています。
開発中に躓いた点は以下の2点です。
import { LoadScript } from "@react-google-maps/api";
~~~
省略
~~~
<LoadScript
googleMapsApiKey={
process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY ?? ""
}
libraries={["places"]}
loadingElement={<div>Loading...</div>}
onLoad={() => console.log("Google Maps script loaded")}
onError={(error) =>
console.error("Error loading Google Maps script", error)
}
>
<Map address={address} />
</LoadScript>
Mapを読み込む際に上記のようにgoogle-mapから提供されているLoadScriptを使用していました。サーバー起動時はマップが描画されるものの、サインインページなどの別ページに遷移したあとに戻ってくるとマップが表示されないバグに直面しました。
仕様をメンターさんと調べてみると「LoadScript がページ遷移前と後で二回スクリプトをロードしようとするのでエラーになってしまう」ことが分かりました。更に調べてみると、Reactを使用したMAPの表示を行っているリポジトリを発見し、以下のようにuseJsApiLoaderを使用する形に変更しました。
import { useJsApiLoader } from "@react-google-maps/api";
~~~
省略
~~~
const { isLoaded } = useJsApiLoader({
id: "google-map-script",
googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY ?? "",
});
~~~
省略
~~~
{isLoaded ? <Map address={address} /> : <div>Loading...</div>}
上記のコードに変更後バグが解消されページ遷移後もマップが表示されるようになりました。
画面表示時のウィンドウサイズを取得し、useStateの初期値を設定したいと考え以下のようなコードを書きました。
const [isMobile, setIsMobile] = useState(window.innerWidth <= 1024);
すると以下のようなエラーが表示
⨯ src/components/Map.tsx (24:44) @ window
⨯ ReferenceError: window is not defined
at Map (./src/components/Map.tsx:27:85)
digest: "2479333777"
22 |
23 | function Map() {
24 | const [isMobile, setIsMobile] = useState(window.innerWidth <= 1024);
| ^
25 |
26 | useEffect(() => {
27 | const handleResize = () => {
GET / 500 in 30ms
調べてみると同じ問題を解決している記事を発見。どうやらNextJS は SSR を前提としているため、window を使おうとするとエラーになってしまうらしいです。Map.tsxでは先頭に"use client"をつけてCSRを宣言してるから大丈夫だと思っていたのですが引っかかっていたようです。記事を参考に以下のようなコードにすることでエラーが解消されました。
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
setIsMobile(window.innerWidth <= 1024);
const handleResize = () => {
setIsMobile(window.innerWidth <= 1024);
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
学外のハッカソンの参加は初めてでしかも即席メンバーという事もあってものすごく不安と緊張を抱えて挑んだハッカソンでしたが、メンバーやメンターの協力もありなんとか発表まで頑張ることができました!!同じフロント班の方は今までHTMLやCSSを軽く触った位でフレームワークを何も知らない状態だったのにもかかわらず、今回最後までやり遂げてくれたのは本当に嬉しかったです。今まで技術を教えて貰う立場ばかりで人をリードする経験がなかったので、NextJSの説明や実装の役割分担などが大変でした(もう少し自分の知識があれば分かりやすく説明できたかな〜と若干後悔)。
あと、全体的なWebの知識が足りないなと感じることが多くありました。バックエンドの方たちと相談する際に、コードやターミナルを見せてもらうことや現在取り掛かっている作業の説明、データのやり取りの仕様決めなどの機会が何度かありました。相槌を打って聞いていたものの正直何を言っているか分からなかったことのほうが多く、開発が進むに連れフロントとバックの理解の齟齬が大きくなっていき最終日まで連携が取れずサーバーで動かせないといったことになってしまいました。ここは本当に反省していて、もっと準備期間に細かいところまで話して担当外のこともしっかり把握できるようにしておくべきでした。ハッカソン終了後の感想会でもメンバーから設計書や図をしっかりと定義しておくべきだったと意見が出ていたので今後のチーム開発では意識していきたいです。
賞は取れませんでしたが、即席チームで最後まで揉めずにやり遂げれたことは良い経験になったと思っています。私も含めて皆でゴールに向かって一週間走り切ることができました。楽しかったのはもちろんですがもっと知識をつけて強くならなくてはと思えるようなハッカソンだったので今後も頑張ります。