首页 > 解决方案 > React - TypeError:无法读取未定义的属性“长度”

问题描述

我正在尝试在 React 中构建表单验证系统,因为表单正在被填写,如下所示:

订单.jsx

import { orderFormRules } from './forms/form-rules.js';
import FormErrors from './forms/FormErrors.jsx';

class Orders extends Component {
  constructor (props) {
    super(props);
    this.state = {
      formClient: {
        client: '',
        phone: '',
        email: '',
        select: '',
      },
      clients:[],
      orderFormRules:orderFormRules,
      valid:false
    };
    this.handleSubmitOrder = this.handleSubmitOrder.bind(this);
    this.handleOrderFormChange = this.handleOrderFormChange.bind(this);
  };

validateForm() {
    // define self as this
    const self = this;
    // get form data
    const formClient = this.state.formClient;
    // reset all rules
    self.resetRules()
    if (self.props.formType === 'Order'){
      const formRules = self.state.orderFormRules;
      if (formClient.client.length > 5) formRules[0].valid = true;
      if (this.validateEmail(formClient.email)) formRules[1].valid = true;
      if (formClient.phone.length > 5) formRules[2].valid = true;
      if (formClient.select.length > 5) formRules[3].valid = true;
      self.setState({formClient: formRules})
      if (self.allTrue()) self.setState({valid: true});
    }
  };

allTrue() {
    let formRules = orderFormRules;
    if (this.props.formType === 'Order') {
      formRules = orderFormRules;
    }
    for (const rule of formRules) {
      if (!rule.valid) return false;
    }
    return true;
  };

  resetRules() {
    const orderFormRules = this.state.orderFormRules;
    for (const rule of orderFormRules) {
      rule.valid = false;
    }
    this.setState({orderFormRules: orderFormRules})
    this.setState({valid: false});
  };

  validateEmail(email) {
    // eslint-disable-next-line
    var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
  };

在处理表单更改时,我要求进行验证,如下所示:

    handleOrderFormChange(event) {
      const obj = this.state.formClient;
      obj[event.target.name] = event.target.value;
      this.setState({ formClient:obj })
      this.validateForm(); 
   };

并在渲染调用中<FormErrors

  render() {

let orderFormRules = this.state.orderFormRules; 
if (this.props.formType === 'Order') {
  orderFormRules = this.state.orderFormRules;
}

return (
  <div>
  <h1 className="title is-1">Register Order</font></h1>
  <FormErrors
        formType={this.props.formType}
        formRules={orderFormRules}
      />
  <div className="Line" /><br/>
   <form onSubmit={ (event) => this.handleSubmitOrder(event) }>
      <div className="field">
         <input
            name="client"
            className="input is-dark is-large"
            type="text"
            placeholder="Client name"
            required
            //value={this.state.formClient.client}
            onChange={this.handleOrderFormChange}
          /> 
      </div>
        <div className="field">
          <input
            name="email"
            className="input is-dark is-large"
            type="email"
            placeholder="Client email"
            required
            //value={this.state.formClient.email}
            onChange={this.handleOrderFormChange}
          />
        </div>
      <div className="field">
        <input
          name="phone"
          className="input is-dark is-large"
          type="text"
          placeholder="Client phone"
          required
          //value={this.state.formClient.phone}
          onChange={this.handleOrderFormChange}
        />
      </div>
      <div className="field">
        <input
          name="select"
          className="input is-dark is-large"
          type="text"
          placeholder="Coffee ordered by client"
          required
          //value={this.state.formClient.select}
          onChange={this.handleOrderFormChange}
        />
      </div>

      <input
        type="submit"
        className="button is-dark is-large is-fullwidth"
        value="Submit"
        //disabled={!this.state.valid}  
      />
      </form>
     </div>
     )
    };
   };

FormErrors.jsx

import React from 'react';

import './FormErrors.css';

const FormErrors = (props) => {
  return (
    <div>
      <ul className="validation-list">
        {
          props.formRules.map((rule) => {
            return <li
              className={rule.valid ? "success" : "error"} key={rule.id}>{rule.name}
            </li>
          })
        }
      </ul>
      <br/>
    </div>
  )
};

export default FormErrors;

表单-rules.js

    export const orderFormRules = [
  {
    id: 1,
    field: 'client',
    name: 'Client real name.',
    valid: false
  },
  {
    id: 2,
    field: 'email',
    name: 'Email is required.',
    valid: false
  },
  {
    id: 3,
    field: 'phone',
    name: 'Phone is required.',
    valid: false
  },
  {
    id: 4,
    field: 'select',
    name: 'Coffee is required.',
    valid: false
  }
];

行为

根据console.log,当我使用cookie(其中任何一个)填写第一个表单时,它会接受第一个项目并将其状态更改为正常。然后在第二次自动填充时中断,或者如果我键入项目,则在任何一次自动填充时中断,并出现以下错误:

TypeError: Cannot read property 'length' of undefined

  56 | if (self.props.formType === 'Order'){
  57 |   const formRules = self.state.orderFormRules;
> 58 |   if (formClient.client.length > 5) formRules[0].valid = true;
     | ^  59 |   if (this.validateEmail(formClient.email)) formRules[1].valid = true;
  60 |   if (formClient.phone.length > 5) formRules[2].valid = true;
  61 |   if (formClient.select.length > 5) formRules[3].valid = true;

完整的控制台:

Orders.jsx:58 Uncaught TypeError: Cannot read property 'length' of undefined
    at Orders.validateForm (Orders.jsx:58)
    at Orders.handleOrderFormChange (Orders.jsx:122)
    at HTMLUnknownElement.callCallback (react-dom.development.js:363)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:412)
    at invokeGuardedCallback (react-dom.development.js:466)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:481)
    at executeDispatch (react-dom.development.js:614)
    at executeDispatchesInOrder (react-dom.development.js:639)
    at executeDispatchesAndRelease (react-dom.development.js:744)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:753)
    at Array.forEach (<anonymous>)
    at forEachAccumulated (react-dom.development.js:723)
    at runEventsInBatch (react-dom.development.js:770)
    at runExtractedPluginEventsInBatch (react-dom.development.js:916)
    at handleTopLevel (react-dom.development.js:6171)
    at batchedEventUpdates (react-dom.development.js:2422)
    at dispatchEventForPluginEventSystem (react-dom.development.js:6271)
    at dispatchEvent (react-dom.development.js:6301)
    at unstable_runWithPriority (scheduler.development.js:674)
    at runWithPriority$2 (react-dom.development.js:11834)
    at discreteUpdates$1 (react-dom.development.js:22935)
    at discreteUpdates (react-dom.development.js:2440)
    at dispatchDiscreteEvent (react-dom.development.js:6254)

我错过了什么?

标签: javascriptreactjs

解决方案


setState()这是问题所在:

validateForm() {
    const self = this;
    const formClient = this.state.formClient;
    self.resetRules()
    if (self.props.formType === 'Order'){
      const formRules = self.state.orderFormRules;
      if (formClient.client.length > 5) formRules[0].valid = true;
      if (this.validateEmail(formClient.email)) formRules[1].valid = true;
      if (formClient.phone.length > 5) formRules[2].valid = true;
      if (formClient.select.length > 5) formRules[3].valid = true;
      // comment this out -----> self.setState({formClient: formRules})
      if (self.allTrue()) self.setState({valid: true});
    }
  };

当我删除该行时,它起作用了。


推荐阅读