如何将 react-intl-tel-input 与 formik 集成?
Posted
技术标签:
【中文标题】如何将 react-intl-tel-input 与 formik 集成?【英文标题】:How to integrate react-intl-tel-input with formik? 【发布时间】:2019-06-24 22:45:14 【问题描述】:我正在使用 Formik 在我的 ReactJs 应用程序中处理表单,我想使用 react-intl-tel-input 来处理电话号码,但是我无法将 handleChange、handleBlur 和验证与 Formik 集成。现在我正在使用我的表单状态来保存电话号码及其验证状态,但这会通过重新渲染我的其他字段而导致 Formik 出现问题。
这是我的电话号码组件:
<IntlTelInput
fieldId="userPhoneNumber"
fieldName="userPhoneNumber"
value=values.userPhoneNumber
preferredCountries=preferredMobileCountries
css=['intl-tel-input', `form-control $(!validPhoneNumber) ? 'is-invalid' : ''`]
style=display: 'block',width: '100%'
format
onPhoneNumberChange=this.handlePhoneChange
/>
!validPhoneNumber && <div className="invalid-feedback">Invalid phone number</div>
实现此目的的正确方法是什么?我的意思是使用自定义组件但能够使用 Formik 的 handleChange、handleBlur 和验证模式?
提前谢谢...
【问题讨论】:
【参考方案1】:这不是最佳解决方案,而是将 IntlTelInput 链接回 formik 的 setFieldTouched 和 setFieldValue。
// @flow
import React, Component, Fragment from 'react';
import ErrorMessage, Field from 'formik';
import IntlTelInput from 'react-intl-tel-input';
export default class MobileField extends Component
formatPhoneNumberOutput(
isValid: boolean,
newNumber: string,
countryData: Object,
fullNumber: string,
isExtension: boolean
)
if (isValid && fullNumber)
return fullNumber.replace(/(\s|-)/g, '');
return 'invalid_phone_number'; // caught by validator
render()
return (
<Field
name=name
render=(field, form: errors, isSubmitting, touched, setFieldTouched, setFieldValue) =>
return (
<Fragment>
<IntlTelInput
defaultCountry="fr"
defaultValue=field.value
disabled=isSubmitting
fieldId=name
fieldName=name
onPhoneNumberBlur=() =>
setFieldTouched(name, true);
onPhoneNumberChange=(...args) =>
setFieldValue(name, this.formatPhoneNumberOutput(...args));
preferredCountries=['fr', 'gb', 'es', 'be', 'de']
/>
<ErrorMessage name=name render=msg => <p>msg</p> />
</Fragment>
);
/>
);
使用 validate.js 等验证器检查电话号码是否不是“invalid_phone_number”
// @flow
import _mapValues from 'lodash/mapValues';
import validate from 'validate.js';
export type Values =
mobile: string,
landline: string
;
export default (values: Values) =>
const options =
fullMessages: false
;
const validation: [key: string]: string[] = validate(
values,
mobile:
presence: message: 'Please add a mobile phone number',
format:
pattern: '^((?!invalid_phone_number).)*$', // is not invalid_phone_number
message: 'This phone number looks like being invalid'
,
landline:
,
options
);
return _mapValues(validation, messages => messages[0]);
;
【讨论】:
您好@gasp 感谢您的回复,但是不完全了解如何将其与 validate.js 集成?我的意思是在哪里可以指定验证手机的规则?【参考方案2】:如果有人希望集成到功能组件(而不是基于类的组件)中,这可能会为您节省一些时间! :)
import React, useState from 'react';
import PropTypes from 'prop-types';
import IntlTelInput from 'react-intl-tel-input';
import Field from 'formik';
import 'react-intl-tel-input/dist/main.css';
const TelephoneInput = ( name, ...props ) =>
const [telephoneValid, setTelephoneValid] = useState(true);
const setValidity = valid =>
setTelephoneValid(valid);
;
// process number into string with area code for submission
const processNumber = (isValid, phone, country) =>
return `+$country.dialCode $phone`;
;
return (
<>
<Field name=name>
(
field: value ,
form: isSubmitting, setFieldTouched, setFieldValue ) =>
<IntlTelInput
...props
containerClassName="intl-tel-input"
inputClassName=telephoneValid ? 'valid' : 'invalid'
label="telephone"
defaultValue=value
disabled=isSubmitting
fieldId=name
fieldName=name
onPhoneNumberBlur=(isValid) =>
setFieldTouched(name, true);
setValidity(isValid);
onPhoneNumberChange=(isValid, phone, country) =>
setFieldValue(name, processNumber(isValid, phone, country));
/>
</Field>
</>
);
;
TelephoneInput.propTypes =
name: PropTypes.string.isRequired,
;
export default TelephoneInput;
【讨论】:
【参考方案3】:如果你使用的是 useFormik 钩子
import IntlTelInput from "react-intl-tel-input";
<IntlTelInput
inputClassName="tel-number"
fieldId="number"
fieldName="number"
onPhoneNumberChange=(
isValid,
value,
selectedCountryData,
fullNumber
) =>
formik.handleChange("number")(fullNumber);
/>
【讨论】:
以上是关于如何将 react-intl-tel-input 与 formik 集成?的主要内容,如果未能解决你的问题,请参考以下文章