Redux-form:在页面顶部显示错误列表

IT技术 javascript reactjs redux redux-form
2021-05-03 15:01:46

我想以更改输入颜色并在页面顶部显示实际错误的方式使用 Redux-form。如何访问字段本身之外的当前字段错误列表?

2个回答

您无法从提供给 Field 组件的渲染函数外部获取错误列表。这是因为错误未存储在 redux 存储中。

编辑 26/12/2018 :

这个答案需要一些时间。ReduxForm 现在将错误存储在 Redux 存储中。看看@nicoqh 的答案,它使用 ReduxForm 的选择器来获取任何 Redux 连接组件中的错误。

这个答案并没有完全过时,但它不再是实现这个恕我直言的最干净的方法。

解决方案 1:对相同的值使用多个 Field

第一种解决方案是对相同的值使用多个 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:使用全局错误props

第二种解决方案是使用全局错误props,但您必须使用reduxForm.

请注意,这是一个完全的反模式!全局错误props用于与字段无关的错误。

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:从商店获取错误

通过将验证函数应用于存储中的值,您始终可以从存储中获取错误。对于大量验证,它可能没有性能,因为它在每次渲染时都经过验证,所以当值改变时它运行两次,如果其他一些 props 改变,它会运行两次。使用异步验证也很困难。

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,它不是在所有的解决方案。请不要在您的应用程序中执行此操作。如果此答案链接到某处,我不会删除历史记录。

您可以使用redux-form 提供状态选择器

特别是,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选择器。