UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

109 lines (86 loc) 5.1 kB
# PhoneInput `PhoneInput` 元件提供了一個使用者友善的國際電話號碼輸入欄位。它與 `react-hook-form` 無縫整合,並包含一個帶有國旗和國碼的可搜尋國家選擇器、自動號碼格式化,以及由 `google-libphonenumber` 支援的強大驗證功能。 此元件旨在與其他表單元素(例如 [`CountrySelect`](./components-ui-form-elements-country-select.md) 或 [`AddressForm`](./components-ui-form-elements-address-form.md))協同工作,透過將其選定的國家與共享的表單欄位同步。 ## 運作方式 該元件利用 `react-international-phone` 函式庫實現其核心功能,並將其包裝以提供與 `react-hook-form` 和 Material-UI 的深度整合。當使用者選擇一個國家或輸入號碼時,該元件會更新表單狀態中對應的欄位。當另一個元件修改表單中連結的國家欄位時,它也會自動更新其國家選擇。 <!-- DIAGRAM_IMAGE_START:architecture:16:9 --> ![PhoneInput](assets/diagram/phone-input-diagram-0.jpg) <!-- DIAGRAM_IMAGE_END --> ## 屬性 `PhoneInput` 元件接受所有標準的 Material-UI `TextField` 屬性,此外還包括以下特定屬性: | 屬性 | 類型 | 是否必須 | 預設值 | 描述 | |---|---|---|---|---| | `name` | `string` | 是 | - | 用於向 `react-hook-form` 註冊電話號碼的欄位名稱。 | | `countryFieldName` | `string` | 否 | `'billing_address.country'` | 儲存所選國家 ISO2 代碼的表單欄位名稱。這使得電話輸入的國家可以與表單的其他部分(例如地址元件)同步。 | ## 使用方式 若要使用 `PhoneInput` 元件,您必須將其包裝在 `react-hook-form` 的 `FormProvider` 中。以下範例展示了一個包含驗證的基本實作。 首先,您需要函式庫提供的非同步驗證函式。 ```javascript phone-validator.js icon=logos: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'; } }; ``` 現在,您可以在您的表單元件中使用此驗證器。 ```jsx MyPaymentForm.tsx icon=logos:react 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. **`name="phone"`**:這會將輸入欄位以 `phone` 的名稱註冊到表單資料中。 3. **`countryFieldName="billing_address.country"`**:這會告知 `PhoneInput` 從表單狀態的 `billing_address.country` 欄位讀取和寫入。這就是它保持同步的方式。在 `useForm` 中,此欄位的預設值被設為 `'us'`。 4. **`rules`**:我們將一個非同步的 `validate` 函式傳遞給 `rules` 屬性。`react-hook-form` 在驗證期間將會等待此函式解析完成。`validatePhoneNumber` 公用程式被呼叫以執行檢查。 ## 與 AddressForm 整合 `PhoneInput` 的真正強大之處在於與 `AddressForm` 一同使用時才能展現。由於兩個元件可以連結到同一個國家欄位(預設為 `billing_address.country`),因此在 `AddressForm` 中變更國家將會自動更新 `PhoneInput` 中的國旗和國碼。 關於此整合的完整範例,請參閱 [`AddressForm`](./components-ui-form-elements-address-form.md) 的文件。