コンテキスト(Context)

コンテキスト(Context)は深い階層にある子コンポーネントにその間にあるすべてのコンポーネントのpropsを介することなく値を渡すことを可能にします。一般的なユースケースはテーマの設定です。端的に言うとコンテキストはPreactでPub-Subスタイルの更新を行う方法だと考えることができます。

コンテキストには2通りの使用方法があります。それは新しいcreateContextAPIと古いコンテキストAPIです。 この2つの違いは古いAPIでは、間にあるコンポーネントがshouldComponentUpdateでレンダリングを中止した場合、その子コンポーネントの更新処理が実行されないことです。 これを理由に、常にcreateContextを使うことを強く推奨します。



createContext

最初にコンポーネント間を通過することができるコンテキストオブジェクを生成する必要があります。 これはcreateContext(initialValue)関数で行います。 createContext(initialValue)はコンテキストの値をセットするために使われるProviderコンポーネントとコンテキストから値を受け取るComsumerコンポーネントを返します。

const Theme = createContext('light');

function ThemedButton(props) {
  return (
    <Theme.Consumer>
      {theme => {
        return <button {...props} class={'btn ' + theme}>Themed Button</button>;
      }}
    </Theme.Consumer>
  );
}

function App() {
  return (
    <Theme.Provider value="dark">
      <SomeComponent>
        <ThemedButton />
      </SomeComponent>
    </Theme.Provider>
  );
}

useContextフックを使うと簡単にコンテキストを扱うことができます。

古いコンテキストAPI

古いコンテキストAPIは主に後方互換性のために存在しており、現在はcreateContextAPIに置き換えられました。 古いコンテキストAPIはコンテキストの値を提供するコンポーネントと受け取るコンポーネントの間にあるコンポーネントがshouldComponentUpdatefalseを返した場合、受け取るコンポーネントの更新処理が実行されない既知の問題があります。 それにもかかわらず使う必要があるなら読み続けてください。

コンポーネントがコンテキストを介してデータを子コンポーネントに渡すには、コンポーネントはgetChildContextメソッドを持つ必要があります。 getChildContextメソッドでは、コンテキストに新しく格納したい値を返します。 コンテキストには関数コンポーネントの第2引数もしくはクラスコンポーネントのthis.contextでアクセスすることができます。

function ThemedButton(props, context) {
  return (
    <button {...props} class={'btn ' + context.theme}>
      Themed Button
    </button>;
  );
}

class App extends Component {
  getChildContext() {
    return {
      theme: 'light'
    }
  }

  render() {
    return (
      <div>
        <SomeOtherComponent>
          <ThemedButton />
        </SomeOtherComponent>
      </div>
    );
  }
}

Built by a bunch of lovely people ubitools.com