跳到主要内容

PhoneInput

PhoneInput 组件提供了一个用户友好的国际电话号码输入字段。它与 react-hook-form 无缝集成,并包含一个带有国旗和拨号代码的可搜索国家选择器、自动号码格式化以及由 google-libphonenumber 提供支持的强大验证功能。

该组件旨在与其他表单元素(例如 CountrySelectAddressForm)协同工作,通过与共享的表单字段同步其所选国家来实现。

工作原理

该组件利用 react-international-phone 库实现其核心功能,并对其进行包装,以提供与 react-hook-form 和 Material-UI 的深度集成。当用户选择一个国家或输入一个号码时,该组件会更新表单状态中相应的字段。当另一个组件修改表单中链接的国家字段时,它也会自动更新其国家选择。

PhoneInput

Props

PhoneInput 组件接受所有标准的 Material-UI TextField props,以及以下特定 props:

Prop类型必需默认值描述
namestring-用于在 react-hook-form 中注册电话号码的字段名称。
countryFieldNamestring'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('电话验证错误:', err);
    // 如果库加载失败,则回退到简单的正则表达式
    const pattern = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/im;
    return pattern.test(phoneNumber) || '无效的电话号码';
  }
};

现在,您可以在表单组件中使用此验证器。

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 || '请输入有效的电话号码。';
              },
            }}
            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 集成

PhoneInputAddressForm 一起使用时,其真正的强大之处就显现出来了。由于两个组件都可以链接到同一个国家字段(默认为 billing_address.country),因此在 AddressForm 中更改国家将自动更新 PhoneInput 中的国旗和拨号代码。

有关此集成的完整示例,请参阅 AddressForm 的文档。