我有一个表单(让我们称之为 LoginContainer ),其上有<Field />
组件:
import { reduxForm, Field } from 'redux-form'
...
class LoginContainer extends Component {
...
render() {
const { handleSubmit, pristine, submitting } = this.props
return (
...
<Field
component={AuthFormInput}
type="password"
name="person_password"
placeholder="Password"
/>
AuthFormInput.jsx
const AuthFormInput = ({
input,
name,
placeholder,
type,
meta: { touched, error },
}) => {
return [
<div className="row-md" key={`${name}_field`}>
<input
placeholder={placeholder}
name={name}
type={type}
className={maybeHasError}
{...input}
/>
</div>, // error display works amazing here, no problem
<div key={`${name}_error`}>{touched && (error && <span className="edit_required">{error}</span>)}</div>,
]
}
问题是,我正在尝试处理AuthFormInput
组件之外的错误,而我无法找到任何允许我从任何地方访问每个字段的touched
状态的解决方案AuthFormInput
以外的<Field />
除外的meta.touched
我是否可以通过LoginContainer
内部getTouchedFields()
访问?{/ p>
Redux-Form似乎没有任何我可以使用的AuthFormInput
功能。
我可以通过验证功能轻松收集当前出错的字段,但我无法找到方法来查看触摸的字段。
我无法找到将数据从
LoginContainer
传递到<Field />
的方法,因为meta.touched
位于它们之间,由Redux-Form内部控制。
有没有办法用Redux-Form V7做到这一点?
我有没有办法创建一个允许我在<Field />
内跟踪.test{
overflow: visible;
}
.container {
margin-top: 100px;
}
.word-container [tooltip-def] {
display: inline-block;
position: relative;
}
.word-container [tooltip-def]:before {
left: 50%;
position: absolute;
transform: translateX(-50%);
border-color: #323232 transparent transparent transparent;
border-style: solid;
border-width: 4px 6px 0 6px;
content: "";
display: none;
top: -6px;
z-index: 99;
}
.word-container [tooltip-def]:after {
left: 150%;
position: absolute;
transform: translateX(-47%);
content: attr(tooltip-def);
background: #323232;
border-radius: 5px;
color: #fff;
display: none;
font-family: open sans;
font-size: 12px;
height: auto;
min-width: 250px;
padding: 5px;
text-align: center;
top: -6px;
transform: translateX(-50%) translateY(-100%);
width: auto;
z-index: 99;
}
.word-container [tooltip-def]:hover:after,
.word-container [tooltip-def]:hover:before {
display: inline-block;
}
的HOC?
答案 0 :(得分:1)
好的,我能够做到这一点,这非常非常重要。
从上述问题的代码中前进,我将其添加到LoginContainer
:
import withFormListener from './withFormListener'
const listeningAuthFormInput = withFormListener(AuthFormInput)
那么,<Field />
成了这个:
<Field
component={listeningAuthFormInput}
type="password"
name="person_password"
placeholder="Password"
/>
HOC环绕文本输入字段(或您想要的任何字段),只需监听道具的更改,然后更新Redux:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { updateField } from './auth_actions'
const withFormListener = function listenToFormField(FormField) {
class WrappedField extends Component {
handleFieldUpdate() {
const { name } = this.props.input
const { touched, error } = this.props.meta
if (touched && error) {
if (this.props[`error_${name}`] === error) return null
return this.props.updateField({ prop: name, value: error })
}
if ((touched && !error) && this.props[`error_${name}`].length) {
return this.props.updateField({ prop: name, value: '' })
}
return null
}
componentDidUpdate() {
this.handleFieldUpdate()
}
render() {
return <FormField {...this.props} />
}
}
const mapStateToProps = ({
auth: { error_person_tel, error_person_password },
}) => ({
error_person_tel, error_person_password,
})
return connect(mapStateToProps, { updateField })(WrappedField)
}
export default withFormListener
从逻辑上讲,HOC中发生的事情是:
this.props
内AuthFormInput
成为HOC内的this.props
this.props.meta
和this.props.input
你应该从LoginContainer
看到我的动作创建者和减速器,所以没有混淆。
行动创作者
export const updateField = ({ prop, value }) => ({
type: AUTH_UPDATE_FIELD,
payload: { prop, value },
})
<强>减速强>
我建议保持状态对象平面。我在这里尝试嵌套,例如:
const INITIAL_STATE = {
errors: { field1, field2 }
}
但是,由于平等原因和避免覆盖errors
的复杂性,它给我带来了更新状态的重大问题。它看起来比它看起来更糟糕。因此,我已经解决了这个问题:
const INITIAL_STATE = {
...
error_person_tel: '',
error_person_password: '',
}
case AUTH_UPDATE_FIELD: {
const { prop, value } = action.payload
return {
...state,
[`error_${prop}`]: value,
}
}
您可以在此处详细了解规范化状态(即:展平): https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html
我根本没有优化它,但这是我如何显示当前的错误(在LoginContainer
内):
<ServerErrors
errors={[
this.props.error_person_tel,
this.props.error_person_password,
].filter(val => val)}
/>
这是一个简单的组件,可以呈现null
或错误字符串数组。
我强烈建议您使用内置的
Redux-Form
字段错误处理。它很棒。遗憾的是,我不得不将控件从字段级别抽象出来以完成UI设计,因此这是V7
中唯一的解决方案。
我搜索了几个星期。我提出了另一个Stack Overflow问题,它没有活动,也没有活动。我很高兴我能够找到一个有效的解决方案。
我还强烈建议您查看Formik
。我几周前在React Native中使用它来完成这个UI要求。您可能会发现它非常有效。如果您遇到任何问题,请在Twitter上与Jared Palmer
对话。由于更智能的架构,Formik与Redux-Form相比具有性能提升。我对React Native感到非常满意。
如果你冒险走这条路,要非常小心地设置由setState
引起的无限循环。我做了数小时和数小时的研究和试验。这个错误:)我对解决方案的简洁性感到满意。如果你有更好的方法,请告诉我。