Redux-form: отображает список ошибок поверх страницы

Я хочу использовать форму Redux таким образом, чтобы изменить цвет ввода и отобразить фактическую ошибку в верхней части страницы. Как получить доступ к списку текущих ошибок полей за пределами самих полей?

Ответ 1

Вы не можете получить список ошибок извне функции рендеринга, данной компоненту Field. Это связано с тем, что ошибки не сохраняются в хранилище избыточности.

ИЗМЕНИТЬ 26/12/2018:

Этот ответ занимает некоторое время. ReduxForm теперь хранит ошибки в магазине Redux. Посмотрите на ответ @nicoqh, который использует селекторы ReduxForm для получения ошибок в любом подключенном компоненте Redux.

Этот ответ не является полностью устаревшим, но это уже не самый чистый способ достичь этого imho.

Решение 1. Используйте несколько полей для одного и того же значения

Первое решение состоит в том, чтобы использовать несколько экземпляров Field для одного и того же значения. Если несколько компонентов Field имеют одно и то же имя и связаны с одним и тем же именем формы, все они будут связаны с одним и тем же значением и одинаковой обработкой ошибок.

Таким образом, вы можете использовать компонент Field и отображать только ошибку.

import React from 'react'
import {reduxForm} from 'redux-form'

const renderError = ({input, meta, ...props}) => (
    <span {...props} className='error'>Error : {meta.error}</span>
)

const renderInput = ({input, meta, ...props}) => (
    <input {...input} {...props} className={meta.error ? 'error' : null} />
)

const FormWithError = ({handleSubmit}) => (
    <div>
        <div className='errorContainer'>
            <Field name='myInput' component={renderError} />
        </div>
        <form onSubmit={handleSubmit}>
            <Field name='myInput' component={renderInput} />
        </form>
    </div>
)

const validate = (values, props) => {
    const errors = {}
    /* calculate errors here by appending theim to errors object */
    return errors
}

export default reduxForm({form: 'myForm', validate})(FormWithError)

Решение 2. Используйте глобальную опору ошибки

Второе решение состоит в том, чтобы использовать глобальные реквизиты ошибок, но вам придется отображать ошибки из компонента контейнера, используя reduxForm.

Обратите внимание, что это полный антипатерн! Опора глобальной ошибки предназначена для ошибок, не зависящих от поля.

import React from 'react'
import {reduxForm} from 'redux-form'

const renderInput = ({input, meta, ...props}) => (
    <input {...input} {...props} className={meta.error ? 'error' : null} />
)

const FormWithError = ({handleSubmit, error}) => (
    <div>
        <div className='errorContainer'>
            <span {...props} className='error'>Error : {error}</span>
        </div>
        <form onSubmit={handleSubmit}>
            <Field name='myInput' component={renderInput} />
        </form>
    </div>
)

const validate = (values, props) => {
    const errors = {}
    /* calculate errors here by appending theim to errors object */
    if(Object.keys(errors) > 0) {
        //You can concatenate each error in a string
        for(key in errors) errors._error += key + ': ' + errors[key]
        //or juste put the errors object in the global error property
        errors._error = {...errors}
    }
    return errors
}

export default reduxForm({form: 'myForm', validate})(FormWithError)

Решение 3: Получить ошибки из магазина

Вы всегда можете получить ошибки из магазина, применив функцию проверки к значению, представленному в магазине. Он может быть неэффективным для тщательной проверки, поскольку он проходит проверку при каждом рендеринге, поэтому он запускается дважды при изменении значения и один раз при изменении какого-либо другого реквизита. Это также может быть трудно сделать с асинхронной проверкой.

import React from 'react'
import {reduxForm, formValueSelector} from 'redux-form'
import {connect} from 'redux'

const renderErrors = errors => {
    const errorNodes = []
    for(key in errors) errorNodes.push(<span className='error'>{key}: {errors[key]}</span>)
    return errorNodes
}

const renderInput = ({input, meta, ...props}) => (
    <input {...input} {...props} className={meta.error ? 'error' : null} />
)

let FormWithError = ({handleSubmit, values, ...otherProps}) => (
    <div>
        <div className='errorContainer'>
            {renderErrors(validate(values, otherProps))}
        </div>
        <form onSubmit={handleSubmit}>
            <Field name='myInput1' component={renderInput} />
            <Field name='myInput2' component={renderInput} />
        </form>
    </div>
)

const validate = (values, props) => {
    const errors = {}
    /* calculate errors here by appending theim to errors object */
    return errors
}

FormWithError = reduxForm({form: 'myForm', validate})(FormWithError)
FormWithError = connect(
    state => formValueSelector('myForm')(state, 'myInput1', 'myInput2')
)(FormWithError)

Последнее решение может заключаться в хранении ошибок в хранилище путем реализации componentWillReceiveProps и отправки действия для обновления списка ошибок в хранилище, но я не думаю, что это действительно хорошая идея. Лучше оставить простой компонент без состояния для визуализации компонента Field.

ИЗМЕНИТЬ 26/12/2018:

Это последнее "решение" не было хорошим, когда я его опубликовал. Но так как componentWillReceiveProps устарел в React, это вовсе не решение. Пожалуйста, не делайте этого в вашем приложении. Я не удаляю это для истории, если этот ответ был где-то связан.

Ответ 2

Вы можете использовать селекторы состояний, предоставляемые при помощи редукционной формы.

В частности, getFormSubmitErrors выдаст вам ошибки проверки отправки:

import { getFormSubmitErrors } from 'redux-form';

// ...

const MyFormWithErrors = connect(state => ({
  submitErrors: getFormSubmitErrors('my-form')(state)
}))(MyForm);

Исходный неподключенный компонент MyForm может выглядеть следующим образом:

const MyForm = reduxForm({
  form: 'my-form',
})(ManageUserProfile);

Если вы хотите отобразить ошибки синхронной проверки, вы можете вместо этого использовать селектор getFormSyncErrors.

Ответ 3

вы можете использовать Fields для сбора всей информации о поле, включая ошибки;

Нажмите Поля !

Насладись щелчком здесь !