コンテキスト(Context)
コンテキスト(Context)は深い階層にある子コンポーネントにその間にあるすべてのコンポーネントのprops
を介することなく値を渡すことを可能にします。一般的なユースケースはテーマの設定です。端的に言うとコンテキストはPreactでPub-Subスタイルの更新を行う方法だと考えることができます。
コンテキストには2通りの使用方法があります。それは新しいcreateContext
APIと古いコンテキスト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は主に後方互換性のために存在しており、現在はcreateContext
APIに置き換えられました。
古いコンテキストAPIはコンテキストの値を提供するコンポーネントと受け取るコンポーネントの間にあるコンポーネントがshouldComponentUpdate
でfalse
を返した場合、受け取るコンポーネントの更新処理が実行されない既知の問題があります。
それにもかかわらず使う必要があるなら読み続けてください。
コンポーネントがコンテキストを介してデータを子コンポーネントに渡すには、コンポーネントは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>
);
}
}