Next.js での useContext
の基本的な使い方
今回は、Next.js を使って useContext
をどうやって活用するのか、そしてどんなときに使うべきなのかをまとめてみました!また、ディレクトリ構成にも触れていきます。
どんな時に使うか?
useContext
は、コンポーネントツリーの深い階層にあるコンポーネントが、状態や関数を簡単に利用できるようにするためのものです。通常、プロップドリリング(props drilling: バケツリレーとも言う)を避けたいときに使います。
例えば、以下のコードを見てください。プロップドリリングが発生している例です。
ディレクトリ構成:
my-next-app/ ├── pages/ │ ├── index.js ├── components/ │ ├── Header.js │ ├── Main.js │ ├── Profile.js
コード:
// pages/index.js import React, { useState } from 'react'; import Header from '../components/Header'; import Main from '../components/Main'; const Home = () => { const [user, setUser] = useState({ name: 'たけし' }); return ( <div> <Header user={user} /> <Main user={user} /> </div> ); }; export default Home;
// components/Header.js const Header = ({ user }) => { return <h1>Welcome, {user.name}!</h1>; }; export default Header;
// components/Main.js import Profile from './Profile'; const Main = ({ user }) => { return ( <div> <Profile user={user} /> </div> ); }; export default Main;
// components/Profile.js const Profile = ({ user }) => { return <p>User's name is {user.name}</p>; }; export default Profile;
このコードでは、user
プロップをツリーの深いところまで渡さなければなりません。これがプロップドリリングです。
最近では、Typescriptも導入されていることが多いので、 Propsの型定義も全てのファイルに記載しなくてはいけなかったり、冗長なコードが増えてしまいます。
useContext を利用したコードとメリットを解説
では、これを useContext
を使って解決してみましょう。Next.js では、コンテキスト関連のファイルを contexts
ディレクトリに格納するのがおすすめです。今回は、ユーザー情報を更新するために、setUser
もコンテキストで渡します。
ディレクトリ構成:
my-next-app/ ├── pages/ │ ├── index.js ├── components/ │ ├── Header.js │ ├── Main.js │ ├── Profile.js │ ├── UpdateUser.js ├── contexts/ │ ├── UserContext.js
コード:
// contexts/UserContext.js import { createContext } from 'react'; const UserContext = createContext(); export default UserContext;
// pages/index.js import React, { useState } from 'react'; import Header from '../components/Header'; import Main from '../components/Main'; import UserContext from '../contexts/UserContext'; const Home = () => { const [user, setUser] = useState({ name: 'たけし' }); return ( <UserContext.Provider value={{ user, setUser }}> <div> <Header /> <Main /> </div> </UserContext.Provider> ); }; export default Home;
// components/Header.js import React, { useContext } from 'react'; import UserContext from '../contexts/UserContext'; const Header = () => { const { user } = useContext(UserContext); return <h1>Welcome, {user.name}!</h1>; }; export default Header;
// components/Main.js import Profile from './Profile'; import UpdateUser from './UpdateUser'; const Main = () => { return ( <div> <Profile /> <UpdateUser /> </div> ); }; export default Main;
// components/Profile.js import React, { useContext } from 'react'; import UserContext from '../contexts/UserContext'; const Profile = () => { const { user } = useContext(UserContext); return <p>User's name is {user.name}</p>; }; export default Profile;
// components/UpdateUser.js import React, { useContext } from 'react'; import UserContext from '../contexts/UserContext'; const UpdateUser = () => { const { setUser } = useContext(UserContext); const handleChangeName = () => { setUser({ name: 'ひろし' }); }; return <button onClick={handleChangeName}>名前をひろしに変更</button>; }; export default UpdateUser;
メリット
- コードのシンプル化:プロップを何度も渡す必要がなくなります。
- メンテナンス性の向上:一度設定すれば、どこからでも簡単にコンテキストにアクセスできるので、変更が楽になります。
- Providerの valueにsetState関数を渡せば良い
- 読みやすさ:プロップドリリングがないので、コードがより読みやすくなります。
まとめ
useContext
は、React や Next.js で状態管理や関数をコンポーネントツリーの深い階層で簡単に共有したいときに非常に便利です。プロップドリリングを避け、コードをよりシンプルかつメンテナンスしやすくしてくれます。Next.js の場合は、contexts
ディレクトリを使ってコンテキストを整理すると良いでしょう。次回のプロジェクトではぜひ試してみてくださいね!
これで、useContext
の基本的な使い方とそのメリットについての説明は終わりです。お読みいただきありがとうございます!