Reactでロケールごとにスタイルを変更する具体的な方法

Reactを使用してWebアプリケーションを開発する際、ユーザーの言語や地域に応じたスタイル変更は、優れたユーザーエクスペリエンスを提供するために重要です。特定の地域や言語では、テキストの方向やフォントの選択、レイアウトの変更が必要となる場合があります。これらの対応を適切に行うことで、アプリケーションの国際化やローカライズを成功させることができます。本記事では、Reactを用いてロケールごとに異なるスタイルを適用する方法を具体的に解説します。

目次

Reactでロケール対応を行う利点


ロケール対応は、ユーザー体験の質を向上させるために欠かせない要素です。以下に、Reactでロケール対応を行う主な利点を挙げます。

1. ユーザーエクスペリエンスの向上


言語や地域特有のデザインやレイアウトを適用することで、ユーザーが直感的に操作できるインターフェースを提供できます。例えば、アラビア語やヘブライ語の右から左へのテキスト方向(RTL)に対応することは、現地ユーザーにとっての使いやすさを大幅に向上させます。

2. グローバル市場への対応


ロケール対応は、多国籍展開を目指すアプリケーションにとって不可欠です。異なる文化や言語に配慮したスタイルを採用することで、幅広い地域のユーザーに対応できます。

3. ブランドイメージの向上


細部にまで気を配ったローカライズ対応は、ブランドの信頼性とプロフェッショナリズムを高めます。ユーザーに対する配慮が感じられるアプリは、競争力を持つだけでなく、顧客満足度を向上させます。

4. アクセシビリティの向上


適切なロケール対応を行うことで、異なるデバイスやユーザー層にも適応可能なインターフェースが実現します。視覚や言語のバリアを軽減するデザインを導入することで、より多くのユーザーを取り込むことができます。

Reactの柔軟性を活かせば、これらの利点を最大限に引き出し、より親しみやすいアプリケーションを構築できます。

言語や地域別スタイル適用の基本概念

Reactで言語や地域に応じたスタイルを適用する際には、アプリケーションのロケール情報を基に、条件付きでスタイルやレイアウトを切り替えるアプローチが基本です。このセクションでは、その基本的な概念と仕組みについて解説します。

1. ロケール情報の収集


アプリケーションがユーザーのロケール情報を取得する方法として、以下のような手法があります:

  • ブラウザの設定を利用: navigator.languagenavigator.languages を使って、ユーザーの言語設定を取得します。
  • ユーザー設定: アプリ内で言語や地域を選択できる設定を提供します。
  • サーバーサイドからの提供: サーバーがユーザーのIPアドレスやプロファイル情報をもとにロケール情報を送信します。

2. ロケールごとのスタイル適用


Reactでは、ロケール情報を基にスタイルを動的に変更できます。たとえば、以下のような方法があります:

  • CSSクラスの動的切り替え: ロケールごとに異なるCSSクラスを適用します。
  const localeClass = userLocale === 'ar' ? 'rtl' : 'ltr';
  return <div className={localeClass}>Hello</div>;
  • CSS-in-JSの活用: スタイルをJavaScriptコードで動的に生成します。
  const styles = {
    textAlign: userLocale === 'ar' ? 'right' : 'left',
  };
  return <div style={styles}>Hello</div>;

3. ロケールに応じた要素のレンダリング


場合によっては、ロケールごとに異なるコンポーネントやUI要素を表示することが必要です。

return userLocale === 'ja' ? (
  <JapaneseComponent />
) : (
  <DefaultComponent />
);

4. ロケール対応の一貫性を保つ


アプリ全体で統一されたロケール管理を行うには、以下のような仕組みが役立ちます:

  • Context API: グローバルにロケール情報を共有し、各コンポーネントで参照可能にします。
  • 状態管理ライブラリ: ReduxやRecoilを使用してロケール情報を集中管理します。

これらの基本的な仕組みを理解することで、Reactアプリにおけるロケールごとのスタイル適用がスムーズに行えるようになります。

Context APIを使ったロケール管理

ReactのContext APIを利用すると、ロケール情報をアプリケーション全体で一貫して管理し、効率的にコンポーネント間で共有できます。このセクションでは、Context APIを用いてロケール管理を実装する手順を解説します。

1. Contextの作成


Context APIでは、まずロケール情報を保持するContextを作成します。

import React, { createContext, useState, useContext } from 'react';

export const LocaleContext = createContext();

export const LocaleProvider = ({ children }) => {
  const [locale, setLocale] = useState('en'); // 初期値を英語に設定

  return (
    <LocaleContext.Provider value={{ locale, setLocale }}>
      {children}
    </LocaleContext.Provider>
  );
};

2. Contextの利用


アプリケーション全体でロケール情報を参照できるよう、LocaleProviderをルートコンポーネントにラップします。

import React from 'react';
import { LocaleProvider } from './LocaleContext';
import App from './App';

const Root = () => (
  <LocaleProvider>
    <App />
  </LocaleProvider>
);

export default Root;

3. ロケール情報の参照


子コンポーネント内でロケール情報を取得するには、useContextフックを使用します。

import React, { useContext } from 'react';
import { LocaleContext } from './LocaleContext';

const Header = () => {
  const { locale } = useContext(LocaleContext);

  return (
    <header>
      <h1>{locale === 'en' ? 'Welcome' : 'ようこそ'}</h1>
    </header>
  );
};

export default Header;

4. ロケールの変更


ユーザーがアプリ内でロケールを切り替えられるようにするには、setLocale関数を使用します。

import React, { useContext } from 'react';
import { LocaleContext } from './LocaleContext';

const LanguageSwitcher = () => {
  const { locale, setLocale } = useContext(LocaleContext);

  const handleChange = (e) => {
    setLocale(e.target.value);
  };

  return (
    <select value={locale} onChange={handleChange}>
      <option value="en">English</option>
      <option value="ja">日本語</option>
    </select>
  );
};

export default LanguageSwitcher;

5. Contextを活用したスタイル管理


ロケール情報を基に、動的にスタイルを変更します。

const StyledComponent = () => {
  const { locale } = useContext(LocaleContext);

  const styles = {
    textAlign: locale === 'ar' ? 'right' : 'left',
    fontFamily: locale === 'ja' ? 'Arial, "Noto Sans JP"' : 'Arial, sans-serif',
  };

  return <div style={styles}>This is a styled component.</div>;
};

Context APIを用いることで、ロケール情報の管理が簡潔になり、アプリ全体でのスタイル変更やUI調整が一貫性を持って実現できます。

スタイルの条件分岐によるロケール適応

ロケールごとにスタイルを変更するには、CSSクラスやインラインスタイルを動的に適用する方法が効果的です。このセクションでは、Reactを使って条件分岐でスタイルを適応する具体的な手法を解説します。

1. CSSクラスの動的切り替え


ロケールに応じて適切なCSSクラスを割り当てる方法です。

例: 条件付きでクラス名を変更

import React, { useContext } from 'react';
import { LocaleContext } from './LocaleContext';

const DynamicClassComponent = () => {
  const { locale } = useContext(LocaleContext);

  const className = locale === 'ar' ? 'rtl-layout' : 'ltr-layout';

  return <div className={className}>Hello World</div>;
};

CSS定義例

.rtl-layout {
  direction: rtl;
  text-align: right;
}

.ltr-layout {
  direction: ltr;
  text-align: left;
}

2. インラインスタイルの使用


スタイルをJavaScriptオブジェクトとして定義し、条件に応じて切り替える方法です。

例: インラインスタイルの動的設定

const DynamicStyleComponent = () => {
  const { locale } = useContext(LocaleContext);

  const styles = {
    textAlign: locale === 'ar' ? 'right' : 'left',
    color: locale === 'ja' ? 'blue' : 'black',
  };

  return <div style={styles}>This text is styled dynamically.</div>;
};

3. CSS-in-JSライブラリの活用


Styled-componentsやEmotionなどのCSS-in-JSライブラリを使用すると、ロケール情報を基にスタイルを変更できます。

例: Styled-componentsを使用した動的スタイル

import styled from 'styled-components';
import { useContext } from 'react';
import { LocaleContext } from './LocaleContext';

const StyledDiv = styled.div`
  text-align: ${(props) => (props.locale === 'ar' ? 'right' : 'left')};
  color: ${(props) => (props.locale === 'ja' ? 'blue' : 'black')};
`;

const CSSInJSComponent = () => {
  const { locale } = useContext(LocaleContext);

  return <StyledDiv locale={locale}>Styled with CSS-in-JS</StyledDiv>;
};

4. コンポーネントの分割によるスタイル管理


ロケールごとに異なるスタイルを持つコンポーネントを分けて管理する方法もあります。

例: ロケール別コンポーネントの作成

const LocaleComponent = () => {
  const { locale } = useContext(LocaleContext);

  if (locale === 'ar') {
    return <div style={{ textAlign: 'right' }}>مرحباً</div>;
  } else if (locale === 'ja') {
    return <div style={{ color: 'blue' }}>こんにちは</div>;
  }
  return <div style={{ textAlign: 'left' }}>Hello</div>;
};

5. ユーザー入力やアクションに基づくスタイル更新


ユーザーのアクションやリアルタイムのロケール変更に対応するスタイルを適用します。

例: ロケール変更に応じた動的更新

import React, { useContext, useState } from 'react';
import { LocaleContext } from './LocaleContext';

const DynamicUpdateComponent = () => {
  const { locale, setLocale } = useContext(LocaleContext);

  const handleSwitchLocale = () => {
    setLocale(locale === 'en' ? 'ja' : 'en');
  };

  const styles = {
    textAlign: locale === 'ja' ? 'center' : 'left',
    backgroundColor: locale === 'ja' ? 'lightblue' : 'lightgray',
  };

  return (
    <div style={styles}>
      <p>The current locale is {locale}</p>
      <button onClick={handleSwitchLocale}>Switch Locale</button>
    </div>
  );
};

これらの手法を組み合わせることで、ロケールに応じたスタイル適応が柔軟に実現できます。どの方法を選ぶかは、プロジェクトの規模や複雑性、チームのスタイル管理ポリシーに応じて決定すると良いでしょう。

国際化ライブラリの活用

ロケールごとにスタイルを変更する際、国際化(i18n)ライブラリを活用することで、効率的かつスケーラブルな方法でロケール管理が可能になります。このセクションでは、Reactでよく使われるi18nライブラリを使用した具体的なアプローチを解説します。

1. i18nextの導入と設定

i18nextは、Reactアプリケーションでロケール管理を行うのに適した強力なライブラリです。

インストール

npm install i18next react-i18next

設定
以下は、i18nextを初期化する方法の例です。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

i18n.use(initReactI18next).init({
  resources: {
    en: {
      translation: {
        welcome: "Welcome",
      },
    },
    ja: {
      translation: {
        welcome: "ようこそ",
      },
    },
  },
  lng: "en", // 初期ロケール
  fallbackLng: "en",
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

2. ロケールごとのスタイル変更


ロケールに応じて動的にスタイルを変更する方法を紹介します。

例: テキストスタイルの切り替え

import React from 'react';
import { useTranslation } from 'react-i18next';

const LocaleBasedStyles = () => {
  const { t, i18n } = useTranslation();

  const styles = {
    textAlign: i18n.language === 'ar' ? 'right' : 'left',
    color: i18n.language === 'ja' ? 'blue' : 'black',
  };

  return <p style={styles}>{t('welcome')}</p>;
};

export default LocaleBasedStyles;

3. React-Intlの利用

React-Intlは、国際化対応を簡素化するための別の人気ライブラリです。

インストール

npm install react-intl

設定
IntlProviderでアプリケーション全体をラップし、ロケール情報を提供します。

import React from 'react';
import { IntlProvider, FormattedMessage } from 'react-intl';

const messages = {
  en: { welcome: "Welcome" },
  ja: { welcome: "ようこそ" },
};

const App = ({ locale }) => {
  return (
    <IntlProvider locale={locale} messages={messages[locale]}>
      <FormattedMessage id="welcome" />
    </IntlProvider>
  );
};

export default App;

4. ロケール変更機能の実装


ユーザーがリアルタイムでロケールを変更できるようにします。

例: i18nextを使用したロケール切り替え

import React from 'react';
import { useTranslation } from 'react-i18next';

const LocaleSwitcher = () => {
  const { i18n } = useTranslation();

  const handleChange = (e) => {
    i18n.changeLanguage(e.target.value);
  };

  return (
    <select onChange={handleChange}>
      <option value="en">English</option>
      <option value="ja">日本語</option>
    </select>
  );
};

export default LocaleSwitcher;

5. ライブラリを活用したデザイン管理


i18nライブラリを利用すると、スタイル管理の一貫性を保ちながら多言語対応が可能です。以下のように、デザインの統一性を持たせることができます。

例: ロケールごとのテーマ適用

import React from 'react';
import { useTranslation } from 'react-i18next';

const ThemedComponent = () => {
  const { i18n } = useTranslation();

  const theme = i18n.language === 'ja' ? 'light-theme' : 'dark-theme';

  return <div className={theme}>This is a themed component.</div>;
};

6. ベストプラクティス

  • ロケール情報を一元管理: Context APIとi18nライブラリを併用して、ロケール情報をアプリ全体で共有する。
  • テキストとスタイルを分離: テキストはi18nライブラリ、スタイルはCSS-in-JSやCSSファイルで管理することで、コードの可読性と保守性を向上させる。

国際化ライブラリを活用すれば、ロケール対応が簡便になり、ユーザーにより良い体験を提供できるようになります。

デザインパターンの最適化

Reactアプリでロケール対応を行う際、効率的かつスケーラブルな設計を実現するには適切なデザインパターンを採用することが重要です。このセクションでは、ロケール対応に適したデザインパターンとその最適化手法について解説します。

1. コンポーネントの再利用性を高める


ロケールごとの違いを吸収する設計にすることで、コンポーネントの再利用性を向上させられます。

例: ロケールに応じたプロップの注入

const LocalizedButton = ({ text, style }) => {
  return <button style={style}>{text}</button>;
};

// 使用例
import { useTranslation } from 'react-i18next';

const App = () => {
  const { t, i18n } = useTranslation();

  const style = {
    textAlign: i18n.language === 'ar' ? 'right' : 'left',
  };

  return <LocalizedButton text={t('submit')} style={style} />;
};

2. コンテナコンポーネントとプレゼンテーショナルコンポーネントの分離


ロケール管理のロジックをコンテナコンポーネントにまとめ、プレゼンテーショナルコンポーネントでスタイルやUIを扱うことで、責任の分離が明確になります。

例: 分離された構造

// コンテナコンポーネント
const LocaleContainer = ({ children }) => {
  const { i18n } = useTranslation();

  const localeProps = {
    textAlign: i18n.language === 'ar' ? 'right' : 'left',
  };

  return React.cloneElement(children, { localeProps });
};

// プレゼンテーショナルコンポーネント
const DisplayComponent = ({ localeProps }) => {
  return <div style={localeProps}>Localized Content</div>;
};

// 使用例
<LocaleContainer>
  <DisplayComponent />
</LocaleContainer>;

3. テーマプロバイダーの活用


ロケールごとのスタイルをテーマとして扱い、ThemeProviderで全体に適用する方法です。

例: Styled-componentsのテーマ設定

import { ThemeProvider } from 'styled-components';

const themes = {
  en: {
    direction: 'ltr',
    fontFamily: 'Arial, sans-serif',
  },
  ar: {
    direction: 'rtl',
    fontFamily: 'Tahoma, sans-serif',
  },
};

const App = () => {
  const { i18n } = useTranslation();
  const currentTheme = themes[i18n.language] || themes.en;

  return (
    <ThemeProvider theme={currentTheme}>
      <MyComponent />
    </ThemeProvider>
  );
};

4. デザイントークンの利用


デザイントークンを導入することで、スタイルやロケールの切り替えが容易になります。

例: デザイントークンの適用

const designTokens = {
  en: {
    color: 'black',
    background: 'white',
  },
  ja: {
    color: 'blue',
    background: 'lightgray',
  },
};

const StyledBox = ({ locale }) => {
  const style = designTokens[locale];

  return <div style={style}>Content with Design Tokens</div>;
};

5. Atomic Designの採用


Atomic Designを用いてコンポーネントを構成することで、ロケールごとのスタイル変更にも柔軟に対応可能な設計を実現できます。

例: ボタンコンポーネントの分離

  • Atoms: テキスト、ボタン
  • Molecules: ボタンとテキストの組み合わせ
  • Organisms: フォームやヘッダーなどのUI部品

この分離により、個々のロケールごとの変更が全体に影響を与えない設計が可能です。

6. ベストプラクティス

  • 柔軟性を持たせる: ロケール情報に基づいて動的に切り替わる設計を取り入れる。
  • 統一性を確保する: スタイルやテーマを一元的に管理し、コンポーネント間で整合性を保つ。
  • 効率性を重視する: ロケール管理ロジックを共通化し、不要な重複を避ける。

これらの最適化手法を採用することで、スケーラブルで保守性の高いロケール対応が可能になります。

実践例:複数ロケールのスタイル変更

このセクションでは、具体的なコード例を通じて、Reactアプリで複数のロケールに応じたスタイル変更を実装する方法を解説します。i18nextを使ったロケール管理と動的なスタイル切り替えの実践例です。

1. 必要なライブラリのインストール


まず、i18nextとそのReactバインディングをインストールします。

npm install i18next react-i18next

2. i18nextのセットアップ


ロケール情報を設定し、Reactアプリで使えるようにします。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

i18n.use(initReactI18next).init({
  resources: {
    en: { translation: { welcome: "Welcome" } },
    ja: { translation: { welcome: "ようこそ" } },
    ar: { translation: { welcome: "مرحبا" } },
  },
  lng: 'en', // 初期ロケール
  fallbackLng: 'en',
  interpolation: { escapeValue: false },
});

export default i18n;

3. ロケール切り替えコンポーネント


ユーザーがリアルタイムでロケールを切り替えるためのUIを作成します。

import React from 'react';
import { useTranslation } from 'react-i18next';

const LocaleSwitcher = () => {
  const { i18n } = useTranslation();

  const handleLocaleChange = (event) => {
    i18n.changeLanguage(event.target.value);
  };

  return (
    <select onChange={handleLocaleChange} value={i18n.language}>
      <option value="en">English</option>
      <option value="ja">日本語</option>
      <option value="ar">العربية</option>
    </select>
  );
};

export default LocaleSwitcher;

4. 動的にスタイルを変更するコンポーネント


ロケールごとのスタイルを動的に適用する実装例です。

import React from 'react';
import { useTranslation } from 'react-i18next';

const LocalizedStyleComponent = () => {
  const { t, i18n } = useTranslation();

  const styles = {
    textAlign: i18n.language === 'ar' ? 'right' : 'left',
    color: i18n.language === 'ja' ? 'blue' : 'black',
    direction: i18n.language === 'ar' ? 'rtl' : 'ltr',
  };

  return (
    <div style={styles}>
      <h1>{t('welcome')}</h1>
      <p>This is a localized component styled dynamically.</p>
    </div>
  );
};

export default LocalizedStyleComponent;

5. アプリ全体への適用


これらのコンポーネントを統合し、アプリケーション全体でロケール切り替えとスタイル変更を実現します。

import React from 'react';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';
import LocaleSwitcher from './LocaleSwitcher';
import LocalizedStyleComponent from './LocalizedStyleComponent';

const App = () => {
  return (
    <I18nextProvider i18n={i18n}>
      <LocaleSwitcher />
      <LocalizedStyleComponent />
    </I18nextProvider>
  );
};

export default App;

6. 実行結果

  • 初期ロケールが英語の場合、Welcomeが左寄せで黒色表示されます。
  • ロケールを日本語(ja)に切り替えると、ようこそが青色で表示されます。
  • ロケールをアラビア語(ar)に切り替えると、مرحباが右寄せで表示されます。

7. 拡張例

  • フォントの切り替え: ロケールに応じてフォントファミリーを動的に変更できます。
  • テーマの適用: Styled-componentsやEmotionを使えば、ロケールごとのテーマを簡単に設定できます。
  • アクセシビリティの向上: テキストサイズや配色の変更により、ユーザー体験をさらに向上させることが可能です。

この実践例を参考にすることで、Reactアプリにおけるロケールごとのスタイル変更を効果的に実装できます。

ロケールごとのスタイルテストとデバッグ

ロケール対応したスタイル変更が正しく機能することを確認するには、徹底的なテストとデバッグが不可欠です。このセクションでは、Reactアプリでロケールごとのスタイル変更をテストし、問題を解決する方法を解説します。

1. テスト環境の準備


ロケールの切り替えとスタイル変更をテストするための環境を整えます。

ブラウザでのロケール設定

  • 各言語や地域に応じた表示確認を行うため、ブラウザのデベロッパーツールで言語設定を変更します。
  • Chrome: 「Settings > Languages」で優先言語を追加。
  • Firefox: 「Preferences > General > Language」で言語を変更。

i18nextのデバッグモード
i18nextの初期化時にdebug: trueを設定して、ロケールの切り替えが正しく動作しているかログを確認します。

i18n.init({
  debug: true,
  // その他の設定
});

2. スタイルのテスト

UIの視覚的テスト

  • 各ロケールに切り替えた状態で、要素の配置やスタイル(色、フォント、方向など)が期待通りになっているか確認します。

テストケース例

  1. 英語(en)ロケールの場合: 左寄せで黒色のテキストが表示される。
  2. 日本語(ja)ロケールの場合: 中央寄せで青色のテキストが表示される。
  3. アラビア語(ar)ロケールの場合: 右寄せで方向がRTLのテキストが表示される。

スクリーンショットテスト
自動化されたUIテストツール(Storybook、Chromaticなど)を使用して、異なるロケールのスタイルをスクリーンショットで比較します。

3. 自動テストの実装

Jestでロケール対応のテスト
Jestを使用して、ロケールごとのスタイルが正しく適用されることを確認します。

import { render } from '@testing-library/react';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';
import LocalizedStyleComponent from './LocalizedStyleComponent';

test('renders with correct styles for en locale', () => {
  i18n.changeLanguage('en');
  const { container } = render(
    <I18nextProvider i18n={i18n}>
      <LocalizedStyleComponent />
    </I18nextProvider>
  );

  expect(container.firstChild).toHaveStyle('text-align: left; color: black');
});

test('renders with correct styles for ar locale', () => {
  i18n.changeLanguage('ar');
  const { container } = render(
    <I18nextProvider i18n={i18n}>
      <LocalizedStyleComponent />
    </I18nextProvider>
  );

  expect(container.firstChild).toHaveStyle('text-align: right; direction: rtl');
});

E2Eテストの活用
CypressやPlaywrightを使って、ロケール切り替えのシナリオをテストします。

describe('Locale Tests', () => {
  it('should apply correct styles for Arabic', () => {
    cy.visit('/');
    cy.get('select').select('ar');
    cy.get('div').should('have.css', 'text-align', 'right');
  });

  it('should apply correct styles for Japanese', () => {
    cy.visit('/');
    cy.get('select').select('ja');
    cy.get('div').should('have.css', 'color', 'blue');
  });
});

4. デバッグ方法

ブラウザのデベロッパーツール

  • 要素のスタイルタブを確認して、適切なスタイルが適用されているかチェックします。
  • レイアウトの方向(LTR/RTL)が正しいか確認します。

ログの活用

  • i18nextのデバッグログを確認し、ロケールの切り替えが正しく機能しているかを確認します。
  • ログにエラーがないかをチェックし、ロケール情報が適切にロードされていることを確かめます。

スタイルの優先度を確認

  • CSSの競合が原因でスタイルが適用されていない場合、!importantinline styleを一時的に使用して原因を特定します。

5. ベストプラクティス

  • カバレッジを高める: 異なるロケールの組み合わせを網羅的にテストする。
  • シナリオベースのテスト: ロケール変更後のナビゲーションやフォーム動作を検証する。
  • ドキュメント化: テスト結果や既知の問題を記録し、チーム全体で共有する。

これらのテストとデバッグ手法を活用することで、Reactアプリのロケール対応スタイル変更が期待通りに動作することを保証できます。

まとめ

本記事では、Reactを用いてロケールごとにスタイルを変更する方法を詳細に解説しました。Context APIや国際化ライブラリ(i18next、React-Intl)を活用してロケール情報を効率的に管理し、動的なスタイル変更を実現する手法を紹介しました。また、デザインパターンやテスト手法を活用することで、スケーラブルで信頼性の高い実装が可能になることを示しました。

ロケール対応のスタイル変更は、ユーザーエクスペリエンスの向上や多言語対応に不可欠な要素です。この記事を参考にして、より多様なユーザーに対応できる魅力的なReactアプリを構築してください。

コメント

コメントする

目次