Next.js(AppRouter)のRouteGroupsで、業務ロジックを簡単に実装しよう
私について
初めまして、川端覇貴です。関西の大学に通う4回生で、インターンエンジニアとして働いています。
業務では、Next.js・Typescript・Railsを使用して、LINE内でお薬を受け取ることができたり、薬剤師の方に悩みを相談できるシステムを開発しています。
概要
業務では、患者さんのUI・UXの向上のために細かい業務ロジックがあります。このような業務ロジックをライブラリの恩恵を受けないで、実装してしまうと複雑性が増してしまう可能性があります。
今回は、実際のアプリ画面を見ていきながら、どのように新しいNext.js(App Router)が使えそうか考察していきたいと思います。
今回の記事はNext13.4以降でStable版になったAppRouterを対象としています。13.4以降になっているかを確認した上で紹介する機能を使用してください。
仕様
上記は、実際のアプリ上で患者さんに服薬指導の予約をしてもらっている画面です。名前の入力画面が終わるまでは、名前とアイコンが表示しないようにしています。ただし、事前に患者さんの名前を知っているケースもあります。その場合は、名前があるかどうかで判断できません。
Route Groupsを使わない実装
(これは実際のコードとはかなり異なります。イメージしやすいためにだいぶ簡略化されています)
const [patient, setPatient] = useState(undefined)
const fetchPatient = () => {
try {
PatientRepository.fetchPatient(token: xxxxx)
} catch(e) {
}
}
// 名前入力前でも知っている可能性がある
const name: null | string = patient.name
const Page = () => (
❌ {name || <IconWithName/> }
)
実際には、名前を見るだけではなく現在どのPathにいるかで判断しないといけません。
const [patient, setPatient] = useState(undefined)
const currentPath = usePathName()
const fetchPatient = () => {
try {
PatientRepository.fetchPatient(token: xxxxx)
} catch(e) {
}
}
// 名前入力前でも知っている可能性がある
const name: null | string = patient.name
// アイコンと名前を表示したいパス
const notShowIconWithNamePath = [ "/name", "/kanaName"]
const isShowIconWithName = !notShowIconWithNamePath.include(currentPath)
&&
name
const Page = () => (
⭕️ {isShowIconWithName || <IconWithName/> }
)
こんな単純なロジックであっても演算子が多すぎて、頭がこんがらがってきます。自分だけかもしれませんが...…
Route Groupsを使った実装
App Routerの基本
AppRouterでRoutingの設定方法を知っている場合は飛ばしてください。
ただここで押さえておくのは1つです。
例えば name Pageを作成したい場合、Appフォルダ内でnameディレクトリを切って、そこにpage.tsx ファイルを作成するだけです。
app/
├ name/
│ └ page.tsx
Route Groups
ここからは、Route Groupsを使った実装について紹介します。
あまりディレクトリに、()を使っているのを見たことがないと思いますが、Next.jsでは()を使うことで、グループ化することができます。
今回はこんな感じでグループ化します。
グループA: 名前とアイコンを表示しない
グループB: 名前とアイコンを表示する
名前とアイコンを表示するディクトリ用にLayoutを作成します。
const Layout: FC<PropsWithChildren<Props>> = ({ name, children}) => {
// SSRで取ってくるとか?
const name: null | string = patient.name
return(
<>
{name || <IconWithName/> }
</>
)
}
フォルダーをグループ化します。
今回はiconWithNameグループに、名前とアイコンを表示するPageを入れます。
ageとbirthdayは名前とアイコンが表示されてほしいため、(iconWithName) ディレクトリに入れました。
(iconWithName) ディレクトリには、さっき紹介したLayout.tsxが入っています。
逆にkananameとnameは app ディレクトリの直下に置いてます。
()が入ったディレクリが入ってしまうと、パスがおかしくなってしまうのではないかと心配された方もいると思いますが、実際にはそうなりません。公式にも書いてます
Route Groupsを使うと何が改善されたのか
Route Groupsを使用することで、以下のような改善点がありました。
Pathに依存したロジックの複雑性がなくなった。
Pathを管理しなくなくなったので Pathを変更した際に、変更漏れなどのリスクがなくなった。
新たにアイコンと名前を表示したいPageがでてきた際に対応がしやすくなった。
ディレクトリ構造をみることでLayoutの適用範囲を見やすくなった。
最後に
この記事では、新しいNext.js(App Router)が使えそうか考察する中で、RouteGroupesを使い、柔軟で単純なロジックにすることができました。インターン先では、まだ Next.js をAppRouterに変更する対応はしていませんが、移行した際はこのような便利な機能を使っていきたいと思います。
PharmaXではインターン生も募集してます。インターン生と正社員の区別なくゴリゴリと成長できる環境ですので、是非!そして何より楽しいです!
PharmaXの採用情報についてはこちらをご覧ください!