React復号:React Hooks関数のuseContext
useContext関数はReact Hooksの3つの基礎hooks関数の1つです.あまり話さないで、まず使い方を見てみましょう.
contextオブジェクト(
注意:
Contextはいつ使用しますか?
Context設計の目的は、現在認証されているユーザー、トピック、または優先言語など、コンポーネントツリーにとって「グローバル」であるデータを共有することです.たとえば、次のコードでは、ボタンコンポーネントのスタイルを「theme」プロパティで手動で調整します.
いくつかのプロパティを階層的に渡すのを避けたい場合は、コンポーネントの組み合わせ(component composition)はcontextよりも良いソリューションである場合があります.
私たちはこのようなシーンを考えています.
PageコンポーネントにはLinkコンポーネントがあり、LinkコンポーネントにはUserコンポーネントがあります.では、データはPageコンポーネントからUserコンポーネントに渡さなければなりません.中間のLinkコンポーネントは、データを処理しません.Userコンポーネントに透過するだけです.しかし、需要変動が必要な場合には、Linkコンポーネントを更新する必要があるので、Reactを使用することができる.Childrenの方法、すなわちslotの方法でコンポーネントを組み合わせます.Context API之
Contextオブジェクトを作成します.ReactがこのContextオブジェクトを購読したコンポーネントをレンダリングすると、このコンポーネントは、コンポーネントツリーの最も近い一致する
Context APIの
各Contextオブジェクトは、消費コンポーネントがcontextの変更を購読できるProvider Reactコンポーネントを返します.
Providerは
Providerの
新旧値検出により変化を決定し,
これを防止するために、valueステータスを親ノードのstateに上げます.
Context APIの
ここで、Reactコンポーネントはcontext変更に購読することもできます.これにより、関数コンポーネントでcontextの購読を完了できます.
これは関数をサブ要素(function as a child)として必要とする.この関数は現在のcontext値を受信し、Reactノードを返します.関数に渡される
Context APIの
動的Context
React.createContext();ダイナミック値をバインドします.
ネストされたコンポーネントでContextを更新する:コンポーネントツリーにネストされた深いコンポーネントからcontextを更新する必要があります.このシーンでは、contextを介して関数を渡し、consumersコンポーネントがcontextを更新することができます.
複数のContextを消費する:contextが迅速に再レンダリングされるように、Reactは各consumersコンポーネントのcontextをコンポーネントツリー内で個別のノードにする必要がある.2つ以上のcontext値が頻繁に使用される場合は、これらの値を提供するために、独自のレンダリングコンポーネントを別途作成することを考慮する必要があります.
これがContexに関する内容です...
const value = useContext(MyContext);
contextオブジェクト(
React.createContext
の戻り値)を受信し、contextの現在の値を返します.現在のcontext値は、上位コンポーネントのうち、現在のコンポーネントに最も近い
のvalue
propによって決定される.コンポーネント上位レイヤの最近の
が更新されると、Hookは再レンダリングをトリガーし、MyContext
providerに最新に渡されたcontext value
の値を使用します.祖先がReact.memo
またはshouldComponentUpdate
を使用していた場合でも、コンポーネント自体がuseContext
を使用しているときに再レンダリングされます.useContext
が呼び出されたコンポーネントは、context値が変化したときに再レンダリングされます.再レンダリングコンポーネントのオーバーヘッドが大きい場合は、memoizationを使用して最適化できます.注意:
useContext(MyContext)
は、contextの値とcontextの変化を読み取ることができるだけです.
を使用して、下位コンポーネントにcontextを提供する必要があります.Contextはいつ使用しますか?
Context設計の目的は、現在認証されているユーザー、トピック、または優先言語など、コンポーネントツリーにとって「グローバル」であるデータを共有することです.たとえば、次のコードでは、ボタンコンポーネントのスタイルを「theme」プロパティで手動で調整します.
// Context , 。
// theme context(“light” )。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// Provider theme 。
// , 。
// , “dark” 。
return (
);
}
}
// theme 。
function Toolbar() { return (
);
}
class ThemedButton extends React.Component {
// contextType theme context。
// React theme Provider, 。
// , theme “dark”。
static contextType = ThemeContext;
render() {
return
使用 context, 我们可以避免通过中间元素传递 props.
Context是最好的解决方案吗?
Context 。 , 。
いくつかのプロパティを階層的に渡すのを避けたい場合は、コンポーネントの組み合わせ(component composition)はcontextよりも良いソリューションである場合があります.
私たちはこのようなシーンを考えています.
PageコンポーネントにはLinkコンポーネントがあり、LinkコンポーネントにはUserコンポーネントがあります.では、データはPageコンポーネントからUserコンポーネントに渡さなければなりません.中間のLinkコンポーネントは、データを処理しません.Userコンポーネントに透過するだけです.しかし、需要変動が必要な場合には、Linkコンポーネントを更新する必要があるので、Reactを使用することができる.Childrenの方法、すなわちslotの方法でコンポーネントを組み合わせます.
const Page = () => { return (
) } const Link = () => { return (
) } const User = () => { return (
) } const data = {name: 'lee'} const App = () => { return (
) }
这种对组件的控制反转减少了在你的应用中要传递的 props 数量,这在很多场景下会使得你的代码更加干净,使你对根组件有更多的把控。但是,这并不适用于每一个场景:这种将逻辑提升到组件树的更高层次来处理,会使得这些高层组件变得更复杂,并且会强行将低层组件适应这样的形式,这可能不会是你想要的。而且你的组件并不限制于接收单个子组件。你可能会传递多个子组件,甚至会为这些子组件(children)封装多个单独的“接口(slots)”.
这种模式足够覆盖很多场景了,在这些场景下你需要将子组件和直接关联的父组件解耦。如果子组件需要在渲染前和父组件进行一些交流,你可以进一步使用 render props。
但是,有的时候在组件树中很多不同层级的组件需要访问同样的一批数据。Context 能让你将这些数据向组件树下所有的组件进行“广播”,所有的组件都能访问到这些数据,也能访问到后续的数据更新。使用 context 的通用的场景包括管理当前的 locale,theme,或者一些缓存数据,这比替代方案要简单的多。
Context API之React.createContext
const MyContext = React.createContext(defaultValue);
Contextオブジェクトを作成します.ReactがこのContextオブジェクトを購読したコンポーネントをレンダリングすると、このコンポーネントは、コンポーネントツリーの最も近い一致する
Provider
から現在のcontext値に読み出されます.defaultValue
パラメータは、コンポーネントが置かれているツリーにProviderが一致していない場合にのみ有効です.これは、Providerパッケージコンポーネントを使用せずにコンポーネントをテストするのに役立ちます.注意:undefined
をProviderのvalueに渡すと、消費コンポーネントのdefaultValue
は有効になりません.Context APIの
React.Provider
各Contextオブジェクトは、消費コンポーネントがcontextの変更を購読できるProvider Reactコンポーネントを返します.
Providerは
value
属性を受信し、消費コンポーネントに渡す.1つのProviderは、複数の消費コンポーネントと対応することができます.複数のProviderをネストして使用することもでき、内側のレイヤは外側のデータを上書きします.Providerの
value
の値が変化すると、その内部のすべての消費コンポーネントが再レンダリングされます.Providerおよびその内部consumerコンポーネントは、shouldComponentUpdate
関数に限定されないため、consumerコンポーネントは、その祖先コンポーネントが更新を終了した場合でも更新することができる.新旧値検出により変化を決定し,
Object.is
と同様のアルゴリズムを用いた.value
にオブジェクトが渡されると、contextがリファレンスID(reference identity)を使用してレンダリングのタイミングを決定するため、providerの親コンポーネントが再レンダリングされるとconsumersコンポーネントで予期せぬレンダリングがトリガーされるトラップがある可能性があります.たとえば、Providerが再レンダリングされるたびに、value
プロパティが常に新しいオブジェクトに割り当てられているため、次のコードは次のconsumersコンポーネントをすべて再レンダリングします.class App extends React.Component {
render() {
return (
);
}
}
これを防止するために、valueステータスを親ノードのstateに上げます.
import React, {useState} from 'react
const App = () => {
const [value, setValue]=useState({something: ''})
render() {
return (
);
}
}
Context APIの
React.Consumer
{value => /* context */}
ここで、Reactコンポーネントはcontext変更に購読することもできます.これにより、関数コンポーネントでcontextの購読を完了できます.
これは関数をサブ要素(function as a child)として必要とする.この関数は現在のcontext値を受信し、Reactノードを返します.関数に渡される
value
の値は、このcontextに最も近いProviderが提供するvalue
の値に等しい.対応するProviderがない場合、value
パラメータは、createContext()
に渡されるdefaultValue
に等しい.Context APIの
React.Consumer
contextオブジェクトは、displayName
というpropertyを受け取り、タイプは文字列です.React DevToolsは、この文字列を使用してcontextが表示する内容を決定します.const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
// "MyDisplayName.Provider" DevTools
// "MyDisplayName.Consumer" DevTools
動的Context
React.createContext();ダイナミック値をバインドします.
ネストされたコンポーネントでContextを更新する:コンポーネントツリーにネストされた深いコンポーネントからcontextを更新する必要があります.このシーンでは、contextを介して関数を渡し、consumersコンポーネントがcontextを更新することができます.
// createContext (consumers) !
export const ThemeContext = React.createContext({
theme: themes.dark, toggleTheme: () => {},});
複数のContextを消費する:contextが迅速に再レンダリングされるように、Reactは各consumersコンポーネントのcontextをコンポーネントツリー内で個別のノードにする必要がある.2つ以上のcontext値が頻繁に使用される場合は、これらの値を提供するために、独自のレンダリングコンポーネントを別途作成することを考慮する必要があります.
// Theme context, theme “light”
const ThemeContext = React.createContext('light');
// context
const UserContext = React.createContext({
name: 'Guest',
});
class App extends React.Component {
render() {
const {signedInUser, theme} = this.props;
// context App
return (
);
}
}
function Layout() {
return (
);
}
// context
function Content() {
return (
{theme => (
{user => (
)}
)}
);
}
これがContexに関する内容です...