---
title: "JSS Reactサンプルアプリでのプレースホルダーの扱い方"
slug: "working-with-placeholders-in-a-jss-react-sample-app"
abstract: "React JSSアプリケーションのためのプレースホルダー技術"
---
# JSS Reactサンプルアプリでのプレースホルダーの扱い方

JSS Reactアプリでプレースホルダーを使う方法はいくつかあります。

> !ヒントプレースホルダーとは何か、どのように機能するかを理解するために、[JSSアプリのプレースホルダー](https://doc.sitecore.com/xp/ja/developers/hd/19/sitecore-headless-development/introducing-placeholders-in-jss-apps.html "Introducing placeholders in JSS apps") ガイドを読むことをお勧めします。

## 基本的なプレースホルダー技術

コンポーネントにプレースホルダーを追加する最も一般的な方法は、Placeholderコンポーネントを使うことです。

import { Placeholder } from '@sitecore-jss/sitecore-jss-react';

const App = ({ rendering }) => (
 <div>
 <h1>My App</h1>
 <Placeholder name="jss-main" rendering={rendering} />
 </div>
);

Placeholder成分について:

-   nameは、あなたが露出させようとしているプレースホルダーの鍵です。
-   renderingは以下を表すことができます:
    -   現在のSitecore提供のレイアウト/ルートデータ。
    -   他のコンポーネント内でプレースホルダーを公開する場合は、親コンポーネントデータを使います。

## 高次成分プレースホルダー技術

高次コンポーネント(HOC)パターンは、プレースホルダー内のコンポーネントの配列をプロパティとして注入し、プレースホルダーを露出させる仕組みです。

import { withPlaceholder } from '@sitecore-jss/sitecore-jss-react';

const Tabs = ({ tabs }) => {
 return (
 <div>
 {tabs}
 </div>
 );
};

export default withPlaceholder('tabs')(Tabs);

コンポーネント配列をエミュレートすると、アプリケーションはエミュレートした場所でコンポーネントをレンダリングします。この手法の主な利点は、ラッパーコンポーネントがないことです。 Placeholderコンポーネントを使用すると、すべての子コンポーネントがコンポーネントツリーの下にレンダリングされます。この方法でプレースホルダーを出すと、そのプレースホルダーにはラップコンポーネントがなく、インラインでレンダリングされます。この方法は、以下の例のように特定のコンポーネント階層に基づくライブラリを使う場合に便利react-fullpage:

<SectionsContainer>
 <Section color="#69D2E7">Page 1</Section>
 <Section color="#A7DBD8">Page 2</Section>
 <Section color="#E0E4CC">Page 3</Section>
</SectionsContainer>

前のサンプルでは、コンポーネント階層がSectionsContainer->Sectionであることが期待されています。もし望むなら、プレースホルダーを使ってSectionコンポーネントを追加し、Sitecore定義することもできます。 Placeholderコンポーネントを使ってこれを行う場合、階層はSectionsContainer -> Placeholder -> YourComponent -> Section:

<SectionsContainer>
 <Placeholder name="jss-sections" rendering={rendering} />
</SectionsContainer>

HOCベースのプレースホルダーを使えば、インラインコンポーネントまたはコンポーネント変換のいずれかでこれを解くことができます。

### インライン部品

ライブラリが単一のコンポーネントラップ層を禁止しない場合は、子コンポーネントをレンダリングコンポーネントに配置できます。 SectionsContainer -> YourComponent -> Sectionのようなコンポーネント階層の取得:

import { withPlaceholder } from '@sitecore-jss/sitecore-jss-react';

const ContainerComponent = ({ sectionsPlaceholder }) => {
 return <SectionsContainer>{sectionsPlaceholder}</SectionsContainer>;
};

// you can also alias the property for the placeholder when using the HOC - or pass an array of placeholders
export const ContainerSitecoreComponent = withPlaceholder({ placeholder: 'sections', prop: 'sectionsPlaceholder' })(ContainerComponent);

// the <Section> is in the child Sitecore component added to the placeholder
export const ChildSitecoreComponent = (props) => (
 <Section>
 <h1>Your JSS or other React components here</h1>
 </Section>
);

### コンポーネント変換

この例のSectionsContainer -> Sectionのように完全にフラットなコンポーネント階層を作りたい場合は、配列であることを活かして、map関数を使って子コンポーネントをラッパーで変換できます。子Sitecoreコンポーネントはラッピングを完全に認識せず、自分のコンテンツのみをレンダリングすることで、この技術を使うことで関心事を明確に分離できます。

const ContainerComponent = ({ sectionsPlaceholder }) => {
 return (
 <SectionsContainer>
 {sectionsPlaceholder.map((component, index) => {
 // this if is important, as it prevents breakage when using Sitecore Experience Editor
 if (component.props && component.props.type === 'text/sitecore') return component;

 // wraps \_all\_ child components in a <Section> component
 return <Section key={index}>{component}</Section>;
 })}
 </SectionsContainer>
 );
};

export const ContainerSitecoreComponent = withPlaceholder({ placeholder: 'sections', prop: 'sectionsPlaceholder' })(ContainerComponent);

## Render Props API

JSS高次コンポーネントよりもレンダープロップスパターンをサポートしています。<Placeholder>コンポーネントのrenderプロパティを使えば、高次コンポーネントと同様にプレースホルダーコンテンツのレンダリングを引き継ぎ、動的プロパティを利用できます。

以下の例は、コンポーネント配列を取得し、renderプロパティを使ってレンダリングする方法を示しています。

import { Placeholder } from '@sitecore-jss/sitecore-jss-react';

const App = ({ rendering }) => (
 <div>
 <h1>My App</h1>
 <Placeholder name="jss-main" rendering={rendering} render={(components, placeholderData, props) => <div>{components}</div>} />
 </div>
);

プレースホルダーのレンダリング関数に対して、オプションで2つの引数を使用できます:

-   propsパラメータは、<Placeholder>に渡される性質のミラーです。
-   placeholderDataパラメータは現在のプレースホルダーのレイアウトデータを提供します。

## 直接的なプレースホルダー内省

もしプレースホルダーのコンポーネントではなくデータにアクセスしたい場合も可能です。この手法の良いユースケースは、タブのようにパーツを2か所(タブタイトルとタブの内容)でレンダリングする必要がある場合です。プレースホルダー階層は大きなオブジェクトJavaScriptなので、props.renderingを使って自分でトラバースして子コンポーネントのデータやフィールドを発見できます:

const Tabs = ({ rendering, tabs }) => (
<Tab.Container>
 <div class="tabsHeading">
 {(rendering.placeholders.tabs || )
 .filter((tab) => tab && tab.fields && tab.fields.title)
 .map((tab, index) => (
 <Tab.Heading key={index}>
 <Text field={tab.fields.title} />
 </Tab.Heading>
 ))}
 </div>

 <div class="tabContents">
 {tabs}
 </div>
</Tab.Container>
);

export default withPlaceholder('tabs')(Tabs);

技術的には、この技術を用いてプレースホルダーを完全カスタムでレンダリングすることも可能ですが、プレースホルダーコンポーネントやHOCを一切使わずに可能です。通常は推奨しません。

## プレースホルダーの強化

Placeholderコンポーネントは開発者体験を向上させるいくつかのカスタマイズをサポートしています。同じカスタマイズは、HOCのプレースホルダーでも、propsTransformerオプションを使って同じプロップを関数で注入することで可能です。

### 誤差成分

プレースホルダーでレンダリングエラーが発生した場合、プレースホルダーはその内容の代わりにエラーコンポーネントを表示し、エラーの詳細をコンソールに記録します。このコンポーネントはerrorComponentプロップを使って自分のReactコンポーネントを置き換えることでカスタマイズできます。

### 欠損コンポーネント

もしプレースホルダーにcomponentFactoryに未知のレンダリング名が含まれている場合(例えば、バックエンド開発者がFooレンダリングを作成しページに追加するが、まだFoo.jsがない場合)、レンダリングはReactコンポーネントのmissingComponentComponentプロパティで定義されたMissingComponentコンポーネントに置き換えられます。デフォルトの実装はシンプルなメッセージですが、missingComponentComponentプロパティで自分のReactコンポーネントを使ってカスタマイズできます。