グローバル依存を隠蔽していないか?Contextを使うHookのレビュー
グローバル依存を隠蔽していないか?Contextを使うHookのレビュー
グローバルステートを共有する目的で導入されるContext構造は、Reactにおける状態管理において有用な仕組みのひとつです。しかし、useXxxContext
のようなカスタムHookを通じてContext値を参照する構造は、一見すると抽象化されているようで、実際には依存元が隠蔽されているだけである場合があります。
レビューアーとしては、こうした構造に潜むグローバル依存の不透明化を見逃さず、「構造としての明快さ」よりも「依存性の可視性」を優先すべき場面を識別する必要があります。
Context構造による依存関係の不明瞭化
useUserContext.ts
const UserContext = createContext<User | null>(null);
export const useUserContext = () => {
const context = useContext(UserContext);
if (!context) throw new Error('No UserContext');
return context;
};
任意のコンポーネント
export const UserProfile = () => {
const user = useUserContext();
return <p>{user.name}</p>;
};
このような構造はReactコードベースでは一般的ですが、以下の観点に注意が必要です。
useUserContext
という命名により、「グローバル依存であること」がコード上で直感的に伝わらない- importパスや使用箇所から依存元が明確にならず、ローカル変数のように錯覚される
- Propsによる依存注入と異なり、「どこで値が供給されているか」の追跡コストが高い
グローバル依存のレビュー例
@Reviewer: useUserContextが暗黙的にグローバルな状態を参照しており、依存元(Provider)が不明瞭になっています。Propsによる明示的な依存伝播が適切でないか、責務単位で再検討してください。
Contextとは
React Contextは、ツリー構造の深い階層に渡って値を共有するための仕組みで、主にグローバルステートのような横断的な依存を扱う際に用いられる。Providerで囲まれた範囲内でuseContext
により値を取得できる。
Context Hookの抽象化と責務の見極め
以下のように、Contextを内包するHookが別のHookやロジックと結合している構造は、責務の追跡をさらに困難にします。
useAdminFeatures.ts
export const useAdminFeatures = () => {
const user = useUserContext();
const canEdit = user.role === 'admin';
const canDelete = user.permissions.includes('delete');
return { canEdit, canDelete };
};
このようなHookを使用すると、実際には「グローバルステート(Context)」に依存しているにも関わらず、呼び出し側からは単なるユーティリティのように見えてしまいます。
Comment
@Reviewer: useAdminFeaturesの実態はグローバル状態への依存に基づいており、利用者側ではその構造が把握しにくい点に注意してください。外部に依存するロジックであることが明示されるよう、命名・構造に工夫が必要です。
Context Hookの依存構造
レビューで問うべき判断基準
- Contextに依存したHookが再利用可能か、または特定画面専用か
- そのHookの責務に対してContext依存が本当に必要か
- Context依存がPropsによる伝播で代替可能でないか
- 呼び出し元のコードから依存構造が追いやすくなっているか
グローバルな依存を伴うHook構造では、ロジックの再利用性・拡張性よりも、依存関係の明示性と構造の可視性が優先されるべきです。