我对React和Redux Form经验不足,请耐心等待。我有一个父组件,在其中添加了一个子组件(FormGenerator),该子组件创建并返回redux表单字段。 FormGenerator无需验证即可工作,但是当我尝试向其添加验证时,redux表单会抛出错误,它不知道如何处理该类型的字段。
调试器显示,在redux表单的hasError.js中,要解析的类型为 type: $$ typeof:Symbol(react.forward_ref),从而引发未知字段类型的错误。
任何有关如何解决此问题的建议将不胜感激。
Redux Form的hasError.js:
var getErrorKeys = function getErrorKeys(name, type) {
switch (type) {
case 'Field':
return [name, name + "._error"];
case 'FieldArray':
return [name + "._error"];
default:
throw new Error('Unknown field type');
}
};
父项:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import './AnswerQuestionnaire.scss';
import { reduxForm } from 'redux-form';
import { getQuestionnaireToTake, submitResponse } from '../../actions/questionnaires';
import FormGenerator from './FormGenerator';
import Spinner from '../../components/Spinner/Spinner';
const formName = "ResponseForm";
class AnswerQuestionnaire extends Component{
componentWillMount(){
this.props.getQuestionnaireById(this.props.match.params.id)
}
render(){
console.log(this.props)
if (this.props.questionnaire && this.props.questionnaire.questionnaireToTake){
return (
<div>
<form onSubmit={this.props.handleSubmit(this.props.submitResponse)}>
<FormGenerator data={this.props.questionnaire.questionnaireToTake} formName={formName}/>
<button type="submit">Submit</button>
</form>
</div>
)
} else {
return (
<Spinner/>
)
}
}
}
const mapStateToProps = (state) => {
return {
...state,
questionnaire : state.questionnaire
}
}
const mapDispatchToProps = (dispatch) => ({
getQuestionnaireById: (id) => { dispatch(getQuestionnaireToTake(id))},
submitResponse: (formValues) => { dispatch(submitResponse(formValues))}
})
export default reduxForm({
form: formName,
})(connect(mapStateToProps,mapDispatchToProps)(AnswerQuestionnaire));
表单生成器:
import React, { Component } from 'react';
import InputField from "../../components/InputField/InputField";
import { connect } from 'react-redux';
import './AnswerQuestionnaire.scss';
import { Field, change, registerField } from 'redux-form';
import Select from '../../components/Select/Select';
import RadioButton from '../../components/RadioButton/RadioButton';
import CheckBox from '../../components/CheckBox/CheckBox';
import { required } from '../../utils/validators';
const stringToComponentMapper = {
RADIO: RadioButton,
CHECKBOX: CheckBox,
TEXT: InputField,
SELECT: Select
}
class FormGenerator extends Component{
constructor(props) {
super(props);
}
componentWillMount(){
//need to register and set values needed for submit and backend object, that we dont need to display on screen,
//this seems hacky but due to time constraints, I'm doing this like this.
if ( this.props.data){
const { questions } = this.props.data;
questions.map((item, index)=>{
let key = `answers.[${index}].id`;
this.props.dispatch(registerField("ResponseForm",key,Field)) ;
this.props.dispatch(change("ResponseForm",key,item.id)) ;
})
}
}
render(){
const { title, description, questions } = this.props.data;
if ( this.props.data){
return (
<div>
<h3>{title}</h3>
<h2>{description}</h2>
{questions.map((item, index)=>{
let fieldName = `answers.[${index}].answer`;
return(<div>
<Field key={index} validate={required} name={fieldName} component={stringToComponentMapper[item.type]} label={`Question #${index}: ${item.question}`} selectValues={item.answersAllowed}/>
</div>)
}
)}
</div>
)
} else {
return (
<div>
Looks like nothing here...
</div>
)
}
}
}
const mapStateToProps = (state) => {
return {
...state,
questionnaire : state.questionnaire
}
}
export default (connect(mapStateToProps)(FormGenerator));