Next.jsの勉強会 vol.4 useState
Next.js App Routerではページやコンポーネントは基本的にServer Componentとして扱われる。
しかし、ボタンをクリックして表示を切り替えるような UI では、ブラウザ上で状態を持つ必要があるため、Client ComponentとuseStateを使用する。
Server ComponentとClient Component
Next.js App Routerでは、何も指定しないコンポーネントは基本的にServer Componentになる。
Server Componentとは、サーバー側でHTMLを作るコンポーネント。
一方で、ユーザー操作や状態管理を扱う場合はブラウザ側で動く必要があるので、Client Componentを使用する。 下記のような場合↓
onClick={() => ...}useState(...)"use client"とは
ファイルの先頭に"use client"を書くと、Client Componentとして扱われる。
"use client";今回作ったコンポーネントでは、useStateとonClickを使うため、ファイルの先頭に "use client"を書いた。
"use client";
import { useState } from "react";"use client" は、コンポーネントの中でユーザー操作やstateを扱うための合図。
useStateとは
useState は、React で「変化する値」を持つための機能。
今回の例では、詳細文を開いているかどうかをisOpenというstateで管理した。
const [isOpen, setIsOpen] = useState<boolean>(false);このコードの意味↓
isOpen
現在の状態
setIsOpen
状態を変更するための関数
useState<boolean>(false)
最初の値は false、型は booleansetIsOpenは自分で作る関数ではない
setIsOpenは、自分で定義した関数ではなく、useStateが自動で用意してくれる、stateを更新するための関数のこと。
const [isOpen, setIsOpen] = useState<boolean>(false);useState は、2つの値を返します。
1つ目: 現在の値
2つ目: その値を変更する関数名前は自由に付けられるが、Reactでは次のような命名が一般的。
const [count, setCount] = useState<number>(0);
const [name, setName] = useState<string>("");
const [isOpen, setIsOpen] = useState<boolean>(false);state名とsetState名の形にすると、読みやすくなる。
useState<boolean>の意味
useState<boolean>は、このstateがboolean型であることを明示している。
const [isOpen, setIsOpen] = useState<boolean>(false);つまり、isOpenにはtrueまたはfalseだけが入る。
今回のように初期値がfalseの場合、TypeScriptは自動でbooleanと推論できるので、実務では次のように書いても動く。
const [isOpen, setIsOpen] = useState(false);ただし、学習中はuseState<boolean>のように明示すると、stateの型を意識しやすくなる。
ボタンで状態を切り替える
ボタンを押したときにisOpenの値を反転させた。
onClick={() => setIsOpen(!isOpen)}!isOpenはbooleanの反転。
false -> true
true -> falseそのため、ボタンを押すたびに開く・閉じるが切り替わる。
表示を切り替える
ボタンの文字は、三項演算子を使ってisOpenの値によって切り替える。
{isOpen ? "閉じる" : "詳細を見る"}isOpen が true なら「閉じる」
isOpen が false なら「詳細を見る」詳細文は、isOpenがtrueのときだけ表示。&&を使うと条件がtrueのときだけJSXを表示する。
{isOpen && (
<p className="mt-4 text-zinc-300">
初回相談では、目的、必要なページ、公開希望時期を一緒に整理します。
</p>
)}ページ全体をClient Componentにしない
今回、useStateを使うのはContactToggleのみ。
そのため、トップページ全体に"use client"を書くのではなく、ContactToggleだけを Client Componentにした。
import { ContactToggle } from "./contact-toggle";<ContactToggle />このように、ユーザー操作が必要な小さな部品だけをClient Componentにすると、ページ全体は Server Componentのまま保てる。