尝试重用带有功能组件的 redux-form
Trying to reuse a redux-form with functional component
我正在尝试构建一个可重用的组件来创建简单的表单,进行验证和处理提交操作。我可以自己使用它,但是当我尝试制作一个功能组件来注入道具时,我陷入了这个错误。
这个class使用组件构建表单
import React from 'react';
import CustomReduxForm from './CustomReduxForm';
class LoginForm extends React.Component {
getFields() {
return [
{
name : 'username',
type : 'text',
label : 'User',
mandatory : true
},
{
name : 'password',
type : 'password',
label : 'Password',
mandatory : true
}
];
}
handleFormSubmit(values) {
console.log(values)
}
render() {
return (
<div>
<div>Test</div>
<CustomReduxForm
formName="LoginForm"
fields={this.getFields()}
onSubmit={this.handleFormSubmit}
/>
</div>
);
}
}
export default LoginForm;
这是构建表单的组件
import React from 'react';
import { reduxForm, Field } from 'redux-form';
function CustomReduxForm(props) {
class CustomForm extends React.Component {
render() {
const { handleSubmit } = this.props;
return (
<div style={{ margin: '30px' }}>
<form onSubmit={handleSubmit(props.onSubmit)}>
{fields.map(myField => renderFieldset(myField))}
<button className="btn btn-primary" type="submit">Submit</button>
</form>
</div>
);
}
}
const renderInput = field => {
return (
<div className={`form-group ${field.meta.touched && field.meta.invalid ? 'has-danger' : ''}`}>
<input
{...field.input}
type={field.type}
className="form-control"
/>
{field.meta.touched && field.meta.error && <div className="text-help">{field.meta.error}</div>}
</div>
);
}
const renderFieldset = customField => {
return (
<div>
<label htmlFor={customField.name}>{customField.label}</label>
<Field
name={customField.name}
component={renderInput}
type={customField.type} />
</div>
);
}
const validate = values => {
const errors = {}
props.fields.forEach((customField) =>
{
if(customField.mandatory && ! values[customField.name]) {
errors[customField.name] = `You must enter a valid value for ${customField.label}!`;
}
});
return errors
}
return reduxForm({
form: props.formName,
validate
})(CustomForm);
};
export default CustomReduxForm;
我已经尝试了不同的方法来导出在 CustomReduxForm 上创建的表单,但仍然没有!
return reduxForm({
form: props.formName,
validate
})(CustomForm);
// or
const FormWrapped = reduxForm({
form: props.formName,
validate
})(CustomForm);
// Non sense, but ..
return FormWrapped;
// or
return <FormWrapped />;
谢谢!
每个 React 组件都必须有 render()
方法。
因此请确保您的功能组件 CustomReduxForm
具有渲染方法。
我想你必须在 render 方法中包装 return:
function render() {
return reduxForm({
form: props.formName,
validate
})(CustomForm);
}
但是,我不确定你为什么要创建一个功能组件,它包装另一个 class 组件等等。
看看official redux form documentation,常规的表单创建方式是怎样的:
import React from 'react'
import { Field, reduxForm } from 'redux-form'
const SimpleForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name"/>
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name"/>
</div>
</div>
<div>
<label>Email</label>
<div>
<Field name="email" component="input" type="email" placeholder="Email"/>
</div>
</div>
<div>
<label>Sex</label>
<div>
<label><Field name="sex" component="input" type="radio" value="male"/> Male</label>
<label><Field name="sex" component="input" type="radio" value="female"/> Female</label>
</div>
</div>
<div>
<label>Favorite Color</label>
<div>
<Field name="favoriteColor" component="select">
<option></option>
<option value="ff0000">Red</option>
<option value="00ff00">Green</option>
<option value="0000ff">Blue</option>
</Field>
</div>
</div>
<div>
<label htmlFor="employed">Employed</label>
<div>
<Field name="employed" id="employed" component="input" type="checkbox"/>
</div>
</div>
<div>
<label>Notes</label>
<div>
<Field name="notes" component="textarea"/>
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
export default reduxForm({
form: 'simple' // a unique identifier for this form
})(SimpleForm)
问题是 CustomReduxForm
的 return 语句。
正确的做法是将其分配给一个变量并使用 JSX 语法,就像您在上一个片段中所做的那样。
const WrappedForm = reduxForm(...)(CustomForm);
return <WrappedForm />
你唯一错过的是也将 CustomReduxForm
的道具传递给 WrappedForm
。
您需要使用 return <WrappedForm {...props} />
现在需要修复代码中的其他错误,例如...
const { fields, handleSubmit } = this.props
而不是使用 const renderFieldset
并执行 {fields.map(myFieldset => renderFieldset(myFieldset)
您可能想使用 const Fieldset = ...
然后 {fields.map((myFieldset, index) => <Fieldset key={index} />)}
它现在应该可以正常工作了。
我正在尝试构建一个可重用的组件来创建简单的表单,进行验证和处理提交操作。我可以自己使用它,但是当我尝试制作一个功能组件来注入道具时,我陷入了这个错误。
这个class使用组件构建表单
import React from 'react';
import CustomReduxForm from './CustomReduxForm';
class LoginForm extends React.Component {
getFields() {
return [
{
name : 'username',
type : 'text',
label : 'User',
mandatory : true
},
{
name : 'password',
type : 'password',
label : 'Password',
mandatory : true
}
];
}
handleFormSubmit(values) {
console.log(values)
}
render() {
return (
<div>
<div>Test</div>
<CustomReduxForm
formName="LoginForm"
fields={this.getFields()}
onSubmit={this.handleFormSubmit}
/>
</div>
);
}
}
export default LoginForm;
这是构建表单的组件
import React from 'react';
import { reduxForm, Field } from 'redux-form';
function CustomReduxForm(props) {
class CustomForm extends React.Component {
render() {
const { handleSubmit } = this.props;
return (
<div style={{ margin: '30px' }}>
<form onSubmit={handleSubmit(props.onSubmit)}>
{fields.map(myField => renderFieldset(myField))}
<button className="btn btn-primary" type="submit">Submit</button>
</form>
</div>
);
}
}
const renderInput = field => {
return (
<div className={`form-group ${field.meta.touched && field.meta.invalid ? 'has-danger' : ''}`}>
<input
{...field.input}
type={field.type}
className="form-control"
/>
{field.meta.touched && field.meta.error && <div className="text-help">{field.meta.error}</div>}
</div>
);
}
const renderFieldset = customField => {
return (
<div>
<label htmlFor={customField.name}>{customField.label}</label>
<Field
name={customField.name}
component={renderInput}
type={customField.type} />
</div>
);
}
const validate = values => {
const errors = {}
props.fields.forEach((customField) =>
{
if(customField.mandatory && ! values[customField.name]) {
errors[customField.name] = `You must enter a valid value for ${customField.label}!`;
}
});
return errors
}
return reduxForm({
form: props.formName,
validate
})(CustomForm);
};
export default CustomReduxForm;
我已经尝试了不同的方法来导出在 CustomReduxForm 上创建的表单,但仍然没有!
return reduxForm({
form: props.formName,
validate
})(CustomForm);
// or
const FormWrapped = reduxForm({
form: props.formName,
validate
})(CustomForm);
// Non sense, but ..
return FormWrapped;
// or
return <FormWrapped />;
谢谢!
每个 React 组件都必须有 render()
方法。
因此请确保您的功能组件 CustomReduxForm
具有渲染方法。
我想你必须在 render 方法中包装 return:
function render() {
return reduxForm({
form: props.formName,
validate
})(CustomForm);
}
但是,我不确定你为什么要创建一个功能组件,它包装另一个 class 组件等等。
看看official redux form documentation,常规的表单创建方式是怎样的:
import React from 'react'
import { Field, reduxForm } from 'redux-form'
const SimpleForm = (props) => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name"/>
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name"/>
</div>
</div>
<div>
<label>Email</label>
<div>
<Field name="email" component="input" type="email" placeholder="Email"/>
</div>
</div>
<div>
<label>Sex</label>
<div>
<label><Field name="sex" component="input" type="radio" value="male"/> Male</label>
<label><Field name="sex" component="input" type="radio" value="female"/> Female</label>
</div>
</div>
<div>
<label>Favorite Color</label>
<div>
<Field name="favoriteColor" component="select">
<option></option>
<option value="ff0000">Red</option>
<option value="00ff00">Green</option>
<option value="0000ff">Blue</option>
</Field>
</div>
</div>
<div>
<label htmlFor="employed">Employed</label>
<div>
<Field name="employed" id="employed" component="input" type="checkbox"/>
</div>
</div>
<div>
<label>Notes</label>
<div>
<Field name="notes" component="textarea"/>
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
export default reduxForm({
form: 'simple' // a unique identifier for this form
})(SimpleForm)
问题是 CustomReduxForm
的 return 语句。
正确的做法是将其分配给一个变量并使用 JSX 语法,就像您在上一个片段中所做的那样。
const WrappedForm = reduxForm(...)(CustomForm);
return <WrappedForm />
你唯一错过的是也将 CustomReduxForm
的道具传递给 WrappedForm
。
您需要使用 return <WrappedForm {...props} />
现在需要修复代码中的其他错误,例如...
const { fields, handleSubmit } = this.props
而不是使用 const renderFieldset
并执行 {fields.map(myFieldset => renderFieldset(myFieldset)
您可能想使用 const Fieldset = ...
然后 {fields.map((myFieldset, index) => <Fieldset key={index} />)}
它现在应该可以正常工作了。