简体   繁体   中英

Trying to reuse a redux-form with functional component

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.

Every React component has to have render() method.

So make sure your functional component CustomReduxForm has render method.

I guess you have to wrap the return in the render method:

function render() {
    return reduxForm({
        form: props.formName,
        validate
    })(CustomForm);
}

However , I'm not sure why you create a functional component, that wraps another class component and so on.

Look at the official redux form documentation , how is the conventional way of creating forms:

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM