如何将 react-intl-tel-input 与 formik 集成?
How to integrate react-intl-tel-input with formik?
我正在使用 Formik 来处理我的 ReactJs 应用程序中的表单,我想使用 react-intl-tel-input 来处理 phone 数字,但是我无法集成 handleChange, handleBlur 和 Formik 验证。现在我正在使用我的表单状态来保存 phone 数字及其验证状态,但这会通过重新呈现我的其他字段而导致 Formik 出现问题。
这是我的 phone 数字组件:
<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 和验证模式?
提前致谢...
这不是最佳解决方案,但将 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 等验证器来检查 phone 号码不是 "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]);
};
如果有人希望集成到功能组件(而不是基于 class 的组件),这可能会节省您一些时间! :)
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;
如果您使用的是 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);
}}
/>
我正在使用 Formik 来处理我的 ReactJs 应用程序中的表单,我想使用 react-intl-tel-input 来处理 phone 数字,但是我无法集成 handleChange, handleBlur 和 Formik 验证。现在我正在使用我的表单状态来保存 phone 数字及其验证状态,但这会通过重新呈现我的其他字段而导致 Formik 出现问题。
这是我的 phone 数字组件:
<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 和验证模式?
提前致谢...
这不是最佳解决方案,但将 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 等验证器来检查 phone 号码不是 "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]);
};
如果有人希望集成到功能组件(而不是基于 class 的组件),这可能会节省您一些时间! :)
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;
如果您使用的是 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);
}}
/>