使用 React-intl 的 Redux-form 字段级验证和错误翻译
Redux-form Field-Level Validation & error translation with React-intl
对于 redux-form,我尝试将字段级验证与 i18n 结合使用。我正在使用 react-intl (https://github.com/yahoo/react-intl),所以我尝试了这个:
<Field name="Label" component={renderField} validate={[required(this.props.intl)]}
带校验功能:
const required = (intl) => (value) => {return value ? undefined : intl.formatMessage({id:"Required"})};
问题:当我在我的字段标签中出现错误时,如果我更改语言,我的字段状态将丢失并且我的错误消息也会消失。
我认为 validate 属性的值不应该在渲染之间改变,因为它会导致字段被重新注册。解决方案是什么?
如何在字段级验证中为验证消息正确集成 react-intl?可能吗?
您不能将验证函数包装到另一个函数中,每次呈现表单时都会构造一个新函数,这将导致字段重新呈现(因为this.props.validate !== nextProps.validate
)。
但是您可以创建 Field
渲染组件并将本地化验证消息作为 props 传递给它。这是示例:
<form>
<Field
name='Label'
component={RenderField} //here you pass field render component
validate={required}
validationMessage={this.props.intl.formatMessage({id: 'Required'})}
/>
{/*rest of the form*/}
</form>
RenderField 组件:
const RenderField = (props) => {
const {validationMessage, meta: {touched, error}} = props;
return <div>
<input
{...props}
/>
{touched &&
(error &&
<div className='error'>
{validationMessage}
</div>)}
</div>;
};
export default RenderField;
或者,如果您需要不同的验证消息取决于验证错误,您可以创建特定的验证函数,将 return formatMessageId
并将 intl
传递给 RenderField
:
const RenderField = (props) => {
const {intl, meta: {touched, error}} = props;
return <div>
<input
{...props}
/>
{touched &&
(error &&
<div className='error'>
{intl.formatMessage(error)}
</div>)}
</div>;
};
如 Igor 所述,这是实现目标的好方法。
React intl 有一种以基本方式注入 intl 的新方法,通过注入你不需要在你的 RenderField
:
中传递 intl
<Form onSubmit={handleSubmit(onSubmit)}>
<Form.Row >
<Field name="shortName" component={RenderField}
label={intl.formatMessage({ id: "component.userShippingAddress.shortNameLabel" })}
placeholder={intl.formatMessage({ id: "component.userShippingAddress.shortNamePlaceholder" })}
>
</Field>
</Form.Row>
{/*rest of the form*/}
</Form>
渲染场:
import React from 'react'
import { Form } from 'react-bootstrap'
import { injectIntl } from "react-intl"
const RenderField = injectIntl(({intl, ...props}) => {
const {input, label, placeholder, type, meta: {touched, error}} = props;
const hasError = touched && error
return (
<Form.Group controlId={input.name} >
<Form.Label>{label}</Form.Label>
<Form.Control isInvalid={hasError}
{...input}
type={type}
placeholder={placeholder ? placeholder : label}
>
</Form.Control>
{hasError && <Form.Control.Feedback type="invalid">{intl ? intl.formatMessage({id: error}) : error}</Form.Control.Feedback>}
</Form.Group>
);
});
export default RenderField;
并且您可以在您的验证中呈现您的自定义错误,只需从 intl 传递您的 id:
export const validate = formValues => {
const errors = {};
if (!formValues.shortName) {
errors.shortName = 'component.userShippingAddress.shortNameNotEmpty';
}
return errors;
};
对于 redux-form,我尝试将字段级验证与 i18n 结合使用。我正在使用 react-intl (https://github.com/yahoo/react-intl),所以我尝试了这个:
<Field name="Label" component={renderField} validate={[required(this.props.intl)]}
带校验功能:
const required = (intl) => (value) => {return value ? undefined : intl.formatMessage({id:"Required"})};
问题:当我在我的字段标签中出现错误时,如果我更改语言,我的字段状态将丢失并且我的错误消息也会消失。
我认为 validate 属性的值不应该在渲染之间改变,因为它会导致字段被重新注册。解决方案是什么?
如何在字段级验证中为验证消息正确集成 react-intl?可能吗?
您不能将验证函数包装到另一个函数中,每次呈现表单时都会构造一个新函数,这将导致字段重新呈现(因为this.props.validate !== nextProps.validate
)。
但是您可以创建 Field
渲染组件并将本地化验证消息作为 props 传递给它。这是示例:
<form>
<Field
name='Label'
component={RenderField} //here you pass field render component
validate={required}
validationMessage={this.props.intl.formatMessage({id: 'Required'})}
/>
{/*rest of the form*/}
</form>
RenderField 组件:
const RenderField = (props) => {
const {validationMessage, meta: {touched, error}} = props;
return <div>
<input
{...props}
/>
{touched &&
(error &&
<div className='error'>
{validationMessage}
</div>)}
</div>;
};
export default RenderField;
或者,如果您需要不同的验证消息取决于验证错误,您可以创建特定的验证函数,将 return formatMessageId
并将 intl
传递给 RenderField
:
const RenderField = (props) => {
const {intl, meta: {touched, error}} = props;
return <div>
<input
{...props}
/>
{touched &&
(error &&
<div className='error'>
{intl.formatMessage(error)}
</div>)}
</div>;
};
如 Igor 所述,这是实现目标的好方法。
React intl 有一种以基本方式注入 intl 的新方法,通过注入你不需要在你的 RenderField
:
<Form onSubmit={handleSubmit(onSubmit)}>
<Form.Row >
<Field name="shortName" component={RenderField}
label={intl.formatMessage({ id: "component.userShippingAddress.shortNameLabel" })}
placeholder={intl.formatMessage({ id: "component.userShippingAddress.shortNamePlaceholder" })}
>
</Field>
</Form.Row>
{/*rest of the form*/}
</Form>
渲染场:
import React from 'react'
import { Form } from 'react-bootstrap'
import { injectIntl } from "react-intl"
const RenderField = injectIntl(({intl, ...props}) => {
const {input, label, placeholder, type, meta: {touched, error}} = props;
const hasError = touched && error
return (
<Form.Group controlId={input.name} >
<Form.Label>{label}</Form.Label>
<Form.Control isInvalid={hasError}
{...input}
type={type}
placeholder={placeholder ? placeholder : label}
>
</Form.Control>
{hasError && <Form.Control.Feedback type="invalid">{intl ? intl.formatMessage({id: error}) : error}</Form.Control.Feedback>}
</Form.Group>
);
});
export default RenderField;
并且您可以在您的验证中呈现您的自定义错误,只需从 intl 传递您的 id:
export const validate = formValues => {
const errors = {};
if (!formValues.shortName) {
errors.shortName = 'component.userShippingAddress.shortNameNotEmpty';
}
return errors;
};