开发者问题收集

无法读取未定义的属性状态

2020-03-30
479

我尝试从表单中获取用户的输入,然后提交该信息,并发出警报,显示用户在正式提交表单之前输入的内容。但是,我不知道如何解决状态未定义的问题。我最初在类组件之外使用了 FormCreate 和 FormDisplay 函数,但仍然出现相同的错误。阅读了几个小时后,我将它们放在函数内部,但仍然出现相同的问题。

我遗漏了什么?

'use strict'

let d = React.createElement;



class FormFind extends React.Component {
    constructor(props) {
      super(props);
      this.state= {firstname: "",
        lastname: "",
        email: "" };

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}




handleChange = (event) => {
this.setState({value: event.target.firstname
});
}

handleSubmit(event) {
alert('Your information is: ' + this.state.value);
event.preventDefault();
}


    render() {


       function FormCreate(props){
        let formMake = React.createElement("label", {key: props.id},React.createElement("br", {},), (React.createElement("input", 
        {type: "text", name: props.item.text, placeholder: props.item.placeholder, size:"auto", required: "required", onChange:(e) => this.setState({value: e.target.value}), 
        value: this.state.value})))

        return formMake
    }

    function FormDisplay(){
        let props = [ {id: 10, text:"fname", placeholder: "Please Enter Your First Name"},
        {id: 11, text: "lname", placeholder: "Please Enter Your Last Name"}, 
        {id: 12, text: "email", placeholder: "Please Enter Your Email"}, 
        {id: 13, text: "Phone", placeholder: "Please Enter Your Phone Number"},
        {id: 14, text: "numtravelers", placeholder: "Please Enter The Number of Children and Adults Going"},
        {id: 15, text: "datetrip", placeholder: "Please Enter Your Date For The Trip"}];  
        var listItems = props.map((item) => FormCreate({key: props.id, item: item})); 

          return(
            React.createElement("div", {}, listItems))
            ;}

            var x = FormDisplay();



      return React.createElement("form", {onSubmit: this.handleSubmit}, (x), React.createElement("input", {type: "submit", value: "Submit"}));

      }
  }

   const domContainer44 = document.getElementById("formfind");

   ReactDOM.render(
     (d(FormFind)),
     domContainer44);```
3个回答

您不应该在 render 内部声明函数。将它们移到类内部并跳过“function”前缀,以便它们属于您的类。

然后将对它们的所有引用更改为 this.FormCreate。

除此之外,我还更改了您将状态设置为输入名称的方式,如下所示:

this.setState({
        [e.target.name]: e.target.value
      }),

这是您的代码,但已实施修复:

'use strict'

let d = React.createElement;

class FormFind extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fname: "",
      lname: "",
      email: "",
      phone: "",
      numtravelers: "",
      datetrip: ""
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    
  	this.formContent = this.FormDisplay();
  }


  handleChange = (event) => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  handleSubmit(event) {
    alert('Your information is: ' + JSON.stringify(this.state));
    event.preventDefault();
  }

  FormCreate(props) {
    let formMake = React.createElement("label", {
      key: props.id
    }, React.createElement("br", {}, ), (React.createElement("input", {
      type: "text",
      name: props.item.text,
      placeholder: props.item.placeholder,
      size: "auto",
      required: "required",
      onChange: (e) => this.setState({
        [e.target.name]: e.target.value
      }),
      value: this.state.value
    })))

    return formMake
  }

  FormDisplay() {
    let props = [{
        id: 10,
        text: "fname",
        placeholder: "Please Enter Your First Name"
      },
      {
        id: 11,
        text: "lname",
        placeholder: "Please Enter Your Last Name"
      },
      {
        id: 12,
        text: "email",
        placeholder: "Please Enter Your Email"
      },
      {
        id: 13,
        text: "phone",
        placeholder: "Please Enter Your Phone Number"
      },
      {
        id: 14,
        text: "numtravelers",
        placeholder: "Please Enter The Number of Children and Adults Going"
      },
      {
        id: 15,
        text: "datetrip",
        placeholder: "Please Enter Your Date For The Trip"
      }
    ];
    var listItems = props.map((item) => this.FormCreate({
      key: props.id,
      item: item
    }));

    return (
      React.createElement("div", {}, listItems));
  }


  render() {

    return React.createElement("form", {
      onSubmit: this.handleSubmit
    }, (this.formContent), React.createElement("input", {
      type: "submit",
      value: "Submit"
    }));

  }
}

const domContainer44 = document.getElementById("formfind");

ReactDOM.render(
  (d(FormFind)),
  domContainer44);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="formfind"></div>
Salmin Skenderovic
2020-03-30

为什么 this.stateundefined

为此,让我们看看您的 render() 在哪里,好吗?

render() {
  function FormCreate(props) {
    let formMake = React.createElement(
      "label",
      { key: props.id },
      React.createElement("br", {}),
      React.createElement("input", {
        type: "text",
        name: props.item.text,
        placeholder: props.item.placeholder,
        size: "auto",
        required: "required",
        onChange: e => this.setState({ value: e.target.value }),
        value: this.state.value
      })
    );

    return formMake;
  }
}

在这里,您所做的是,在 render() 内创建了一个全新的函数 FormCreate() 。虽然永远不应该这样做,但我们假设在我们的例子中可以这样做。

错误是在 FormCreate() 中的 value: this.state.value 行处引发的。这是因为 FormCreate() 中的 this 引用的是 FormCreate 本身,而不是我们的 React 组件,在这里是 FormFind

注意: FormCreateFormCreate() 不同。

由于 FormCreate 内部没有 state 键,因此 this.state (或 FormCreate.state )为 undefined 。这正是您收到错误的原因。

render() {
  function FormCreate(props) {
    // `this` inside this function refers to itself,
    // i.e `this === FormCreate`

    // since state isn't declared in FormCreate, 
    // FormCreate.state is undefined

    let formMake = React.createElement(
      "label",
      { key: props.id },
      React.createElement("br", {}),
      React.createElement("input", {
        // ...
        onChange: e => this.setState({ value: e.target.value }),
        value: this.state.value // or FormCreate.state.value
      })
    );

    return formMake;
  }
}

解决方案

FormCreate() 提取为方法并将其放在 render() 之外。并且,永远不要忘记在 render() 方法中返回 React Element 或 null

如果您想要完整的代码,请在评论中提问,但由于您正在学习,我希望您自己尝试一下。

Pushkin
2020-03-30
import React, { Component, createElement } from 'react' 
const cE = createElement; // you dont need this... the createElement above does the job

class FormFind extends Component {
    constructor(props) {
        super(props);
        this.state = { //intitialized the state, with all properties I plan on having in it 
            firstName: "", 
            lastName: "",
            email: "",
            phone: "",
            numberOfTravelers: "",
            dateTrip: "",
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        //there are two functions that I did not bind directly in the constructor
        //formCreate = () => {}
        //formDisplay = () => {}
        //When written in this format they function as if you had bound them in the constructor 
        //as you did handleChange() and handleSubmit()

    }

    handleChange(event) {
        //you had this function creating a new key:value pair with 'value' as the key, not a value from any input 
        //but the string 'value' was being used as the key, and you were giving it a value of undefined because
        //event.target.firstName isnt a part of the input element you just used, instead you would use the name 
        //property of the input element. 
        this.setState({
            [event.target.name]: event.target.value
        });
    }

    handleSubmit(event) {
        event.preventDefault();

        const { firstName, lastName } = this.state
        const fullName = firstName + " " + lastName;

        alert('Your information is: ' + fullName);        
    }

    formCreate = (props) => {
        console.log("PROPS", props)
        let formMake = createElement(
            "label",
            { key: props.key },
            createElement("br", {}),
            (createElement(
                "input",
                {
                    type: "text",
                    name: props.item.text,
                    placeholder: props.item.placeholder,
                    size: "auto",
                    required: "required",
                    onChange: (e) => this.handleChange(e),

                    //You have a handleChange() function that wasnt being used, and
                    //you were trying to setState({}) similar to the way I explained it on the 
                    //handleChangea() function. 

                    // If you would like to use setState()
                    // onChange: (e) => this.setState({ [e.target.name]: e.target.value }),
                    value: this.state.value,
                }
            ))
        )
        return formMake
    }

    formDisplay = () => { 
        let props = [{ id: 10, text: "firstName", placeholder: "Please Enter Your First Name" },
        { id: 11, text: "lastName", placeholder: "Please Enter Your Last Name" },
        { id: 12, text: "email", placeholder: "Please Enter Your Email" },
        { id: 13, text: "phone", placeholder: "Please Enter Your Phone Number" },
        { id: 14, text: "numberOfTravelers", placeholder: "Please Enter The Number of Children and Adults Going" },
        { id: 15, text: "dateTrip", placeholder: "Please Enter Your Date For The Trip" }];
        var listItems = props.map((item) => this.formCreate({ key: item.id, item: item }));

        return (cE("div", {}, listItems));
        //the above cE() is the React.createElement() that we initialized at the top, cE is ambiguous
        //and was used only to press that intializing React.createElement() twice, lines 1 & 2, before using 
        //it is unnecessary and names that are stripped down to far are confusing and bad practice.  

    }
    render() {          

        var x = this.formDisplay();
        return createElement("form", { onSubmit: this.handleSubmit }, (x), createElement("input", { type: "submit", value: "Submit" }));
    }
}

export default FormFind 

我改变了一些东西,但我相信这就是你想要的。你唯一需要修复的是显示用户信息。

用户的每次击键都会导致重新绘制每个输入元素,而不仅仅是用户正在输入的元素。它有效,但似乎效率低下。如果这是我没有看到的设计,那就这样吧。一个简单的观察。

花点时间通读 React 文档,一旦点击,React 就很棒。 https://reactjs.org/

也请查看此信息,它在我整理表单元素时对我有帮助 https://www.taniarascia.com/getting-started-with-react/

Jasper
2020-03-31