🎨

画像付きプロフィールカードを作ろう【HubSpot × React DAY7】


目次

はじめに 🌿

社員紹介ページやチームメンバー紹介など、「写真+名前+ひとこと紹介」をまとめて表示したいときってあるよね。
そんなときに活躍するのが、画像付きプロフィールカード

今回は、HubSpot CMS × React を使って、ページ編集画面から画像・名前・紹介文を自由に入力できるプロフィールカードを作っていきます🐱💻

パソコンでプロフィールカードを作る猫のイラスト


この記事でわかること ✏️

  • HubSpotの ImageField を使った画像フィールドの作り方

  • CMS編集画面で画像・テキストを編集できるモジュール構成

  • RepeatedFieldGroup を使って複数人表示する方法

  • dangerouslySetInnerHTML の意味と使いどころ


結論 🎯

ImageFieldRichTextField を組み合わせれば、
社員紹介カードが簡単に作れる!
さらに RepeatedFieldGroup を使えば複数人対応もできちゃう✨


Step1:1人分のプロフィールカードを作ろう 🧸

まずは基本の1人分プロフィールカードを作ってみよう!
画像・名前・役職・紹介文をセットで表示していくよ。

👇 まずは完成イメージの動作はこちら

react_day07

サンプルコード(1人表示)

components/modules/07_ProfileCard/index.jsx
// フィールドの読み込み
import {
  ModuleFields,
  TextField,
  ImageField,
  RichTextField,
} from '@hubspot/cms-components/fields';
// デフォルト画像の読み込み
import image from '../../../assets/charo.png';

// fieldValues の宣言
export function Component({ fieldValues }) {
  const { src, alt, width, height } = fieldValues.image;
// 実際にページに返される情報
  return (
    <div
      style={{
        backgroundColor: '#faf0e6',
        borderRadius: '12px',
        padding: '24px',
        maxWidth: '400px',
        textAlign: 'center',
        margin: '0 auto',
        boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
      }}
    >
      <img
        src={src}
        alt={alt}
        width={width}
        height={height}
        style={{ borderRadius: '50%', marginBottom: '16px' }}
      />
      <h2>{fieldValues.name_hi}</h2>
      <div style={{ fontStyle: 'italic', color: '#666' }}>
        <span>{fieldValues.position}</span>
      </div>
      <div
        style={{ marginTop: '12px', fontSize: '14px', color: '#333' }}
        dangerouslySetInnerHTML={{ __html: fieldValues.bio }}
        // HTML文字列を表示させるための書き方
      />
    </div>
  );
}
components/modules/07_ProfileCard/index.jsx

// フィールドの設定
export const fields = (
  <ModuleFields>
    <ImageField
      name="image"
      label="プロフィール画像"
      default={{ src: image, height: 100, alt: 'プロフィール画像' }}
      resizable={true}
    />
    <TextField
      name="name_hi"
      label="名前"
      default="サンプル ちゃろ"
    />
    <TextField
      name="position"
      label="役職"
      default="フロントエンドエンジニア"
    />
    <RichTextField
      name="bio"
      label="紹介文"
      default="<p>Reactと猫が好きなエンジニアです。</p>"
    />
  </ModuleFields>
);

// モジュールのメタ情報
export const meta = {
  label: '07_プロファイルカード',
};

Step2:複数人のプロフィールを繰り返し表示しよう 🐾

応用編として、今度はチーム紹介のように複数人分のカードを表示してみましょう。
Reactでのループ処理とCMSフィールドを組み合わせるだけで、かなり柔軟に使えるモジュールに!

👇 複数表示のモジュールの動きはこんな感じ

react_day07_1

サンプルコード(繰り返し対応)

components/modules/07_ProfileCard/index.jsx
import {
  ModuleFields,
  TextField,
  ImageField,
  RichTextField,
  RepeatedFieldGroup,
  // 追加で繰り返しフィールドを読み込む
} from '@hubspot/cms-components/fields';
import image from '../../../assets/charo.png';

export function Component({ fieldValues }) {
  const { cards } = fieldValues;

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '20px', justifyContent: 'center' }}>
      {cards?.map((card, index) => {
      // map () を使って配列から表示させる
        const { image, name_hi, position, bio } = card;
        return (
          <div
            key={index}
            style={{
              backgroundColor: '#faf0e6',
              borderRadius: '12px',
              padding: '24px',
              maxWidth: '300px',
              textAlign: 'center',
              boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
            }}
          >
            <img
              src={image.src}
              alt={image.alt}
              width={image.width}
              height={image.height}
              style={{ borderRadius: '50%', marginBottom: '16px' }}
            />
            <h2>{name_hi}</h2>
            <div style={{ fontStyle: 'italic', color: '#666' }}>{position}</div>
            <div
              style={{ marginTop: '12px', fontSize: '14px', color: '#333' }}
              dangerouslySetInnerHTML={{ __html: bio }}
            />
          </div>
        );
      })}
    </div>
  );
}
components/modules/07_ProfileCard/index.jsx
// RepeatedFieldGroupを追加
export const fields = (
  <ModuleFields>
    <RepeatedFieldGroup
      name="cards"
      label="カード一覧"
      occurrence={{ min: 1, max: 10, default: 1 }}
      default={[
        {
          image: { src: image, alt: 'プロフィール画像', height: 100 },
          name_hi: 'サンプルちゃろ',
          position: 'フロントエンドエンジニア',
          bio: '<p>Reactと猫が好きなエンジニアです。</p>',
        },
      ]}
    >
      <ImageField
        name="image"
        label="プロフィール画像"
        default={{ src: image, height: 100, alt: 'プロフィール画像' }}
        resizable={true}
      />
      <TextField name="name_hi" label="名前" default="サンプルちゃろ" />
      <TextField name="position" label="役職" default="フロントエンドエンジニア" />
      <RichTextField
        name="bio"
        label="紹介文"
        default="<p>Reactと猫が好きなエンジニアです。</p>"
      />
    </RepeatedFieldGroup>
  </ModuleFields>
);

export const meta = {
  label: '07_プロファイルカード(複数対応)',
};

 

繰り返しフィールド、map の書き方については以下記事を参考にしてね:

 

💡

フィールド名の注意点

RepeatedFieldGroup を使うときは、フィールドの name と default のキー名を完全に一致させる必要があるよ!
たとえば name="name_hi" にしているなら、default の中も name_hi にしておかないと、初期値が反映されないので注意👀

 


🧠 dangerouslySetInnerHTML って何?

dangerouslySetInnerHTML は、HTMLタグつきの文字列(たとえば <p>〜</p>)をReactでそのまま表示したいときに使う特別な書き方になります。

なんで必要なの?

Reactは <p>こんにちは</p> のようなHTMLタグを含む文字列を、普通の文字列として表示しちゃうんだよね。
だから、これはHTMLとして描画してね!ってわざわざ指示してあげないといけない。

<div dangerouslySetInnerHTML= />

これを使うと、CMSから入力された <p><strong> などのタグがちゃんと適用されて表示されるようになるの。

⚠️

「dangerously」がついている理由

名前がちょっと怖いのは、セキュリティ上の理由から。
たとえば悪意のある <script> タグなんかが混ざってたら危険ですよね(・。・;
だからReactは「これほんとに描画して大丈夫?危なくない?」ってあえて警告っぽくしてあるようです

でもHubSpotの RichTextField は、CMS側でちゃんと安全に処理してくれるから、基本的には安心して使ってOK(のはず)!

 


まとめ ✨

Reactモジュールでも、ImageFieldRichTextField を使えば、
CMSで編集しやすくて見た目もかわいいプロフィールカードが作れちゃう!

RepeatedFieldGroup を使って繰り返しフィールドを追加すれば、チーム紹介や社員紹介ページにもばっちり対応できるよ!

プロフィールカードを表示したモニターを見つめる女性のイラスト


あわせて読みたい 📖

Reina

Written by Reina

HubSpot CMS (現 Content Hub) をメインに 気になったことをまとめます #vibe coding

💬 コメントしてみる?