Redux-form Field-Level Validation&使用React-intl进行错误翻译

时间:2018-03-28 07:10:05

标签: javascript reactjs redux redux-form 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"})};

问题:当我的字段标签出现错误时,如果我更改语言,我的字段状态将丢失,我的错误消息将消失。

我认为验证道具的价值不应该在渲染之间发生变化,因为它会导致重新注册该字段。解决方案是什么?

如何在Field-Level Validation中正确地将react-intl集成到验证消息中?有可能吗?

2 个答案:

答案 0 :(得分:5)

你不能将验证函数包装到另一个函数中,每次渲染表单时它都会构造一个新函数,这将导致字段重新渲染(因为this.props.validate !== nextProps.validate)。

但是您可以创建Field渲染组件并将本地化验证消息作为道具传递给它。这是一个例子:

<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;

或者,如果您需要具有不同的验证消息取决于验证错误,您可以创建将返回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>;
};

答案 1 :(得分:0)

正如 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;
  };