Search code examples
javascriptreactjsreduxredux-formreact-intl

Redux-form Field-Level Validation & error translation with React-intl


With redux-form, I try to use Field-Level Validation with i18n. I'm using react-intl (https://github.com/yahoo/react-intl), so I tried this:

<Field name="Label" component={renderField} validate={[required(this.props.intl)]}

With validation function :

const required = (intl) => (value) => {return value ? undefined : intl.formatMessage({id:"Required"})};

The issue : When I have an error in my field Label, if I change language, the state of my field is lost and my error message disappear.

I think that the value of validate props should not change between renders as it causes the field to be re-registered. What is the solution ?

How can I integrate correctly react-intl for validation messages in Field-Level Validation? Is it possible ?


Solution

  • You cann't use validation function wrapped into another function, every time the form is rendered it will construct a new function, which will cause field to rerender (because this.props.validate !== nextProps.validate).

    But you can create Field render component and pass localized validation message as props to it. Here is example:

    <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 component:

    const RenderField = (props) => {
        const {validationMessage, meta: {touched, error}} = props;
    
        return <div>
            <input
                {...props}
            />
            {touched &&
            (error &&
                <div className='error'>
                    {validationMessage}
                </div>)}
        </div>;
    };
    
    export default RenderField;
    

    Or, if you need to have different validation messages depends on validation errors, you can create specific validation functions that will return formatMessageId and pass intl to RenderField:

    const RenderField = (props) => {
        const {intl, meta: {touched, error}} = props;
    
        return <div>
            <input
                {...props}
            />
            {touched &&
            (error &&
                <div className='error'>
                    {intl.formatMessage(error)}
                </div>)}
        </div>;
    };