Dynamic Form: TypeError: Cannot read property '

2019-07-22 08:04发布

问题:

RESOLVED

Issue was that onChange took a wrong value.

public onChange = (e:any, key:any) => {
  this.setState({
    [key]: e.target.value
  });
};

I seem to have trouble getting rid of an error when entering data into my form. I am using TSX React.

The goal is to be able to create a form dynamically. The issue I kept running into is that the value of my inputs cannot be read. I was wondering if anyone could look at my code and maybe spot my mistake, I am pretty clueless at this point.

I am using the latest @types/react

DynamicForm.tsx

import * as React from "react";

export interface InterfaceDynamicFormProps {
  title: string;
  text: string;
  model: Array<{
    key: string;
    label: string;
    inputs: string;
    type: string;
    value: any;
  }>;
  onSubmit: (model: any) => void;
}

export default class DynamicForm extends React.Component<
  InterfaceDynamicFormProps
> {
  public state = {
  };

  constructor(props: any) {
    // Fetch all properties
    super(props);
  }

  public onSubmit = (e: any) => {
    e.preventDefault(); // Prevent full refresh
    if (this.props.onSubmit) {
      this.props.onSubmit(this.state);
    }
  };

  public onChange = (e:any, key:any) => {
    this.setState({
      [key]: this[key].value **THIS PART CANNOT READ THE VALUE OF MY FORM**
    })
  };

  public renderForm = () => {
    const model = this.props.model;

    const formUI = model.map(m => {
      const key = m.key;
      const type = m.type || "text"; // default text
      const inputs = m.inputs; // default input set to empty

      return (
        <div key={key} className="form-inline">
          <div className="col-sm-4 text__new-item">
            <label
              className="form-label"
              key={"l" + m.key} // Adding l to make a unique key. "l" for label
              htmlFor={m.key}
            >
              {m.label}
            </label>
          </div>
          <div className="col-sm-8 new-item--input form-inline">
            <input
              className={inputs}
              type={type}
              key={"i" + m.key} // Adding i to make a unique key. "i" for input
              onChange={(e)=>{this.onChange(e, key)}}          
            />
          </div>
        </div>
      );
    });
    return formUI;
  };

  // Render Title area and content box
  public render() {
    const title = this.props.title;
    const text = this.props.text;

    return (
      <div className="container container__body">
        <div className="row">
          <div className="col-sm-12">
            <div className="body__title-page">
              <a>
                <p>{title}</p>
              </a>
              <h2>{text}</h2>
            </div>
          </div>
        </div>

        {/* Render form area */}
        <div className="container">
          <div className="top__input">
            <div className="row">
              <div className="col-sm-12 col-lg-4">
                <div className="row">
                  <div className="col-12">
                    <form
                      className="dynamic-form"
                      onSubmit={e => {
                        this.onSubmit(e);
                      }}
                    >
                      {this.renderForm()}
                      <div className="form-group">
                        <button type="submit">submit</button>
                      </div>
                    </form>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

Here is my input from a different file where I call the component:

component.tsx

<DynamicForm 
  title="Facturatie"
  text="Nieuwe factuur aanmaken"
  model={[ // Creates form labels and inputs, binds the
      { key: 'factuurnummmer',  label: 'Factuurnummer:',    inputs: 'smallInput', type: 'text', value: ''},
      { key: 'datum',           label: 'Datum:',            inputs: 'smallInput', type: 'text', value: ''},
      { key: 'opdrachtgever',   label: 'Opdrachtgever:',    inputs: 'smallInput', type: 'text', value: ''},
      { key: 'referentie',      label: 'Referentie:',       inputs: 'smallInput', type: 'text', value: ''},
      { key: 'factuurnummer',   label: 'Factuurnummer:',    inputs: 'smallInput', type: 'text', value: ''},
      { key: 'factuuradres',    label: 'Factuuradres:',     inputs: 'smallInput', type: 'text', value: ''},
      { key: 'debiteurennummer',label: 'Debiteurennummer:', inputs: 'smallInput', type: 'text', value: ''},
      { key: 'email',           label: 'Email:',            inputs: 'smallInput', type: 'text', value: ''},
      { key: 'btw',             label: 'BTW:',              inputs: 'smallInput', type: 'text', value: ''},
      { key: 'btwbedrag',       label: 'BTW bedrag:',       inputs: 'smallInput', type: 'text', value: ''},
      { key: 'exclbtw',         label: 'Excl BTW:',         inputs: 'smallInput', type: 'text', value: ''},
      { key: 'totaalbedrag',    label: 'Totaal Bedrag:',    inputs: 'smallInput', type: 'text', value: ''},      
  ]}
  onSubmit = {(model) => {this.onSubmit(model)}} // submit prop
/>

回答1:

You want to use the value of the event target instead.

public onChange = (e:any, key:any) => {
  this.setState({
    [key]: e.target.value
  });
};