I'm trying to build a reusable component to create simple forms, having validation and handling submit actions. I able to use it by it self, but when I try to make a functional component to inject props I got stuck in this error.
This class uses the component to build forms
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;
This is the component to build forms
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;
I already tried different ways to export the created form on CustomReduxForm, but still nothing!
return reduxForm({
form: props.formName,
validate
})(CustomForm);
// or
const FormWrapped = reduxForm({
form: props.formName,
validate
})(CustomForm);
// Non sense, but ..
return FormWrapped;
// or
return <FormWrapped />;
Thanks!
The problem is the return statement of CustomReduxForm
.
The correct one is to assign it to a variable and use JSX syntax like what you did in the last snippet.
const WrappedForm = reduxForm(...)(CustomForm);
return <WrappedForm />
The only thing you missed is to also pass the props of CustomReduxForm
to the WrappedForm
.
You'll need to use return <WrappedForm {...props} />
Now it's a matter of fixing the other errors in your code like...
const { fields, handleSubmit } = this.props
Instead of using const renderFieldset
and doing {fields.map(myFieldset => renderFieldset(myFieldset)
You might want to use const Fieldset = ...
then {fields.map((myFieldset, index) => <Fieldset key={index} />)}
It should now work as expected.