admin管理员组

文章数量:1403443

I'm trying to build a reusable ponent 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 ponent to inject props I got stuck in this error.

This class uses the ponent 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;

I'm trying to build a reusable ponent 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 ponent to inject props I got stuck in this error.

This class uses the ponent 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 ponent 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}
            ponent={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!

Share Improve this question asked Feb 3, 2017 at 13:54 Klaus EtgetonKlaus Etgeton 1182 silver badges6 bronze badges 2
  • Your last idea of returning <FormWrapped /> should be enough. Do you have any errors with this idea? If yes, what are them? Also, could you please create a JSFiddle/JSBin/Webpackbin that reproduces your problem? – gustavohenke Commented Feb 3, 2017 at 15:54
  • Thanks for the reply, now I get this to work, I followed jpdelatorre advice. Looks like there was more missing parts. Thanks again! – Klaus Etgeton Commented Feb 7, 2017 at 16:13
Add a ment  | 

2 Answers 2

Reset to default 5

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 ponent has to have render() method.

So make sure your functional ponent 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 ponent, that wraps another class ponent 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" ponent="input" type="text" placeholder="First Name"/>
        </div>
      </div>
      <div>
        <label>Last Name</label>
        <div>
          <Field name="lastName" ponent="input" type="text" placeholder="Last Name"/>
        </div>
      </div>
      <div>
        <label>Email</label>
        <div>
          <Field name="email" ponent="input" type="email" placeholder="Email"/>
        </div>
      </div>
      <div>
        <label>Sex</label>
        <div>
          <label><Field name="sex" ponent="input" type="radio" value="male"/> Male</label>
          <label><Field name="sex" ponent="input" type="radio" value="female"/> Female</label>
        </div>
      </div>
      <div>
        <label>Favorite Color</label>
        <div>
          <Field name="favoriteColor" ponent="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" ponent="input" type="checkbox"/>
        </div>
      </div>
      <div>
        <label>Notes</label>
        <div>
          <Field name="notes" ponent="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)

本文标签: javascriptTrying to reuse a reduxform with functional componentStack Overflow