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

时间:2020-03-30 02:13:47

标签: javascript state reactjs

我试图从用户那里以表单的形式输入信息,然后以警告的形式提交该信息,并显示用户在正式提交表单之前输入表单的内容。但是,我无法弄清楚如何解决未定义状态的问题。我最初在类组件之外具有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 个答案:

答案 0 :(得分:1)

您不应该在render内部声明函数。将它们移到班级中,然后跳过“功能”前缀,以便它们属于您的班级。

然后将所有对其的引用更改为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>

答案 1 :(得分:1)

为什么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;
  }
}

您所做的就是在FormCreate()内创建了一个全新的函数render()。尽管绝对不应该这样做,但我们认为可以。

value: this.state.value内的行FormCreate()处引发了错误。这是因为this中的FormCreate()是指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()之外。并且永远不要忘记在null方法中返回React元素或render()

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

答案 2 :(得分:1)

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/组合在一起时,它对我有帮助