Context
基本的な例
アクティブなテーマを含むコンテキストを作成する基本的な例を以下に示します。
import { createContext } from "react";
type ThemeContextType = "light" | "dark";
const ThemeContext = createContext<ThemeContextType>("light");
コンテキストを必要とするコンポーネントをコンテキストプロバイダーでラップします
import { useState } from "react";
const App = () => {
  const [theme, setTheme] = useState<ThemeContextType>("light");
  return (
    <ThemeContext.Provider value={theme}>
      <MyComponent />
    </ThemeContext.Provider>
  );
};
useContextを呼び出して、コンテキストを読み取ったりサブスクライブしたりします。
import { useContext } from "react";
const MyComponent = () => {
  const theme = useContext(ThemeContext);
  return <p>The current theme is {theme}.</p>;
};
default context valueなし
意味のあるデフォルト値がない場合は、nullを指定します。
import { createContext } from "react";
interface CurrentUserContextType {
  username: string;
}
const CurrentUserContext = createContext<CurrentUserContextType | null>(null);
const App = () => {
  const [currentUser, setCurrentUser] = useState<CurrentUserContextType>({
    username: "filiptammergard",
  });
  return (
    <CurrentUserContext.Provider value={currentUser}>
      <MyComponent />
    </CurrentUserContext.Provider>
  );
};
コンテキストの型がnullになる可能性があるため、usernameプロパティにアクセスしようとすると、'currentUser' is possibly 'null'というTypeScriptエラーが発生することに注意してください。usernameにアクセスするにはオプションチェーニングを使用できます。
import { useContext } from "react";
const MyComponent = () => {
  const currentUser = useContext(CurrentUserContext);
  return <p>Name: {currentUser?.username}.</p>;
};
ただし、コンテキストがnullにならないことはわかっているので、nullをチェックしないようにするほうが望ましいです。これを行う1つの方法は、コンテキストが提供されていない場合にエラーがスローされるコンテキストを使用するカスタムフックを提供することです。
import { createContext } from "react";
interface CurrentUserContextType {
  username: string;
}
const CurrentUserContext = createContext<CurrentUserContextType | null>(null);
const useCurrentUser = () => {
  const currentUserContext = useContext(CurrentUserContext);
  if (!currentUserContext) {
    throw new Error(
      "useCurrentUser has to be used within <CurrentUserContext.Provider>"
    );
  }
  return currentUserContext;
};
これを実装時に、ランタイムの型の確認を使用すると、コンポーネントをプロバイダーが適切にラップしていないときに、コンソールに明確なエラーメッセージが表示されるという利点があります。これで、nullをチェックすることなくcurrentUser.usernameにアクセスできます。
import { useContext } from "react";
const MyComponent = () => {
  const currentUser = useCurrentUser();
  return <p>Username: {currentUser.username}.</p>;
};
タイプアサーションを代替として
nullをチェックするのを避けるもう1つの方法は、コンテキストがnullではないことをTypeScriptに伝えるタイプアサーションを使用することです。
import { useContext } from "react";
const MyComponent = () => {
  const currentUser = useContext(CurrentUserContext);
  return <p>Name: {currentUser!.username}.</p>;
};
別のオプションは、デフォルト値として空のオブジェクトを使用し、予想されるコンテキストの型にキャストすることです。
const CurrentUserContext = createContext<CurrentUserContextType>(
  {} as CurrentUserContextType
);
非nullアサーションを使用して同じ結果を得ることもできます。
const CurrentUserContext = createContext<CurrentUserContextType>(null!);
何をすべきかわからない場合は、タイプアサーションよりもランタイムチェックとスローを行います。