コンポーネントを関数に渡して新しいコンポーネントを返す場合、それは高階コンポーネント(HOC)と呼ばれます。 それが単純に聞こえるなら、それはそうです! そして、あなたのコードはそれらを使用するためにより簡単になります。
この投稿の過程で、高次のコンポーネントの抽象化によって、作業がより読みやすく、再利用可能で、構成可能になる方法がわかります。
いくつかの用語
先に進む前に、の高次バージョンを作成しているものを定義しましょう。 これらの定義は同じ意味で使用されているように見えるかもしれませんが、それらの違いに注意することが重要です。
- Node :DOMにマウントされたHTML要素。 ブラウザがそれをレンダリングしており、JavaScriptがそれを操作できます。
- Instance :コンポーネントクラスのランタイムインスタンス。 これらは、メモリ内のJavaScriptオブジェクトとして表されます。
- Element :ノードまたはインスタンスになる可能性のあるものを説明するマークアップのビット。 Reactでは、これらはJavaScriptオブジェクトにトランスパイルされ、実行時にインスタンスになります。
- Component :要素の抽象化。 それらはいくつかの内部状態を持っているかもしれません、そしてそれらは彼らが受け取る小道具に応じて異なった振る舞いをするかもしれません。 レンダリングを求められると、コンポーネントは要素を返します。
- 高階コンポーネント(HOC):コンポーネントの抽象化。 コンポーネント(およびおそらく他のいくつかのパラメーター)が与えられると、それらは新しいコンポーネントを返します。
飛び込む
アプリのユーザーページで作業を開始しようとしているとします。 User オブジェクトがどのように見えるかはわかっていますが、使用する認証の種類はまだ決まっていません。 後で正しい道を決めるときに、どうすれば心痛を避けることができますか? ページがすでに完成している3か月後に、どのように考えが変わる可能性を予測しますか?
withUserという名前の単純なHOC関数から始めることができます。 この関数は、渡されたすべてのコンポーネントをラップアラウンドし、Userオブジェクトを小道具として提供する必要があります。
const withUser = WrappedComponent => {
class WithUser extends React.Component {
constructor(props) {
super(props);
this.state = {
user: sessionStorage.getItem("user")
};
}
render() {
return <^>{...this.props} />;
}
}
return WithUser;
};<^>
説明:
- 私たちの関数
withUserは、引数として任意のコンポーネントを取ります。 - 内部では、
sessionStorageからUserオブジェクトを読み取り、それを状態に追加するWithUserコンポーネントクラスを作成します。 - レンダリング関数は、
WrappedComponentを状態からのユーザーpropを持つ新しい要素として返します。 - 外側の
this.propsを内側のWrappedComponentに渡します。
または、状態が不要な場合は、機能的なHOCを使用することをお勧めします。
const withUser = WrappedComponent => {
const user = sessionStorage.getItem("user");
return props => ;
};
HOCを使用する
ページ上のUserオブジェクトにアクセスする場合は、withUserを呼び出してページのコンポーネントをラップできます。
const UserPage = props => (
<div class="user-container">
<p>My name is {props.user}!</p>
</div>
);
export default withUser(UserPage);
そしてそれはそれをします! withUser関数は、引数としてコンポーネントを受け取り、より高次のコンポーネントを返します。 今から3か月後、状況を変えることにした場合は、HOCを編集するだけで済みます。
野生で
これまでHOCに慣れていなかった場合は、気付かずにHOCに遭遇した可能性があります。 いくつかの注目すべき例:
- react-redux :
connect(mapStateToProps, mapDispatchToProps)(UserPage) - react-router :
withRouter(UserPage) - Material-ui :
withStyles(styles)(UserPage)
ボーナス
reduxのcompose機能を使用すると、複数のHOCを1つにまとめることができます。 例えば:
import { compose } from 'redux';
// ... other imports
export default compose(
withStyles(styles),
withRouter,
withUser
)(UserPage);
この場合、スタイル、ルーター、ユーザーはすべてUserPageコンポーネントに渡されます。