メインコンテンツへスキップ

PhoneInput

PhoneInputコンポーネントは、ユーザーフレンドリーな国際電話番号入力フィールドを提供します。react-hook-formとシームレスに統合され、国旗と国番号付きの検索可能な国選択機能、自動番号フォーマット、およびgoogle-libphonenumberによる強力な検証機能を備えています。

PhoneInputコンポーネントは、ユーザーフレンドリーな国際電話番号入力フィールドを提供します。react-hook-formとシームレスに統合され、国旗と国番号付きの検索可能な国選択機能、自動番号フォーマット、およびgoogle-libphonenumberによる強力な検証機能を備えています。

このコンポーネントは、選択された国を共有フォームフィールドと同期させることで、CountrySelectAddressFormなどの他のフォーム要素と連携して動作するように設計されています。

仕組み

このコンポーネントは、react-international-phoneライブラリをコア機能として活用し、それをラップしてreact-hook-formおよびMaterial-UIとの深い統合を提供します。ユーザーが国を選択したり番号を入力したりすると、コンポーネントはフォームの状態にある対応するフィールドを更新します。また、他のコンポーネントがフォーム内のリンクされた国フィールドを変更すると、自動的に国選択を更新します。

PhoneInput

Props

PhoneInputコンポーネントは、すべての標準的なMaterial-UIのTextField propsに加えて、以下の特定のpropsを受け入れます:

PropTypeRequiredDefaultDescription
namestringYes-react-hook-formに電話番号を登録するためのフィールド名。
countryFieldNamestringNo'billing_address.country'選択された国のISO2コードを保存するフォームフィールドの名前。これにより、電話番号入力の国を、アドレスコンポーネントなど、フォームの他の部分と同期させることができます。

使用方法

PhoneInputコンポーネントを使用するには、react-hook-formFormProviderでラップする必要があります。次の例は、検証機能を含む基本的な実装を示しています。

まず、ライブラリが提供する非同期検証関数が必要です。

phone-validator.js

javascript
// src/libs/phone-validator.js
import { getPhoneUtil } from '@blocklet/payment-react/libs/phone-validator';

export const validatePhoneNumber = async (phoneNumber) => {
  if (!phoneNumber) return true;
  try {
    const util = await getPhoneUtil();
    const parsed = util.parseAndKeepRawInput(phoneNumber);
    return util.isValidNumber(parsed);
  } catch (err) {
    console.error('Phone validation error:', err);
    // ライブラリの読み込みに失敗した場合、単純な正規表現にフォールバックします
    const pattern = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/im;
    return pattern.test(phoneNumber) || 'Invalid phone number';
  }
};

これで、このバリデータをフォームコンポーネントで使用できます。

MyPaymentForm.tsx

jsx
import { FormProvider, useForm } from 'react-hook-form';
import { Button, Box } from '@mui/material';
import { PhoneInput } from '@blocklet/payment-react';
import { validatePhoneNumber } from '../libs/phone-validator'; // 必要に応じてパスを調整してください

export default function MyPaymentForm() {
  const methods = useForm({
    mode: 'onBlur',
    defaultValues: {
      phone: '',
      'billing_address.country': 'us', // デフォルトの国
    },
  });

  const onSubmit = (data) => {
    alert(JSON.stringify(data, null, 2));
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Box display="flex" flexDirection="column" gap={2}>
          <PhoneInput
            label="Phone Number"
            name="phone"
            // フォームの状態にある国フィールドへのリンク
            countryFieldName="billing_address.country"
            // 検証ルールを追加
            rules={{
              validate: async (value) => {
                const isValid = await validatePhoneNumber(value);
                return isValid || 'Please enter a valid phone number.';
              },
            }}
            fullWidth
          />
          <Button type="submit" variant="contained">
            Submit
          </Button>
        </Box>
      </form>
    </FormProvider>
  );
}

解説

  1. `FormProvider`

    PhoneInputを含むフォーム全体がFormProviderでラップされ、必要なフォームコンテキストを提供します。

  2. `rules`

    非同期のvalidate関数をrules propに渡します。react-hook-formは検証中にこの関数が解決されるのを待ちます。チェックを実行するためにvalidatePhoneNumberユーティリティが呼び出されます。

AddressFormとの統合

PhoneInputの真価は、AddressFormと併用することで発揮されます。両方のコンポーネントは同じ国フィールド(デフォルトではbilling_address.country)にリンクできるため、AddressFormで国を変更すると、PhoneInputの国旗と国番号が自動的に更新されます。

この統合の完全な例については、AddressFormのドキュメントを参照してください。