Невозможно прочитать состояние свойства undefined - PullRequest
0 голосов
/ 30 марта 2020

Я пытаюсь получить данные от пользователя в форме, а затем отправить эту информацию с предупреждением, в котором показано, что пользователь ввел в форму, прежде чем официально отправить ее. Тем не менее, я не могу понять, как решить проблему состояния неопределенным. Первоначально у меня были функции 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 ]

1 голос
/ 30 марта 2020

Почему this.state это undefined?

Для этого давайте посмотрим на 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.

ПРИМЕЧАНИЕ: FormCreate отличается от FormCreate().

, поскольку 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(). И никогда не забывайте возвращать React Element или null в методе render().

Если вам нужен полный код, спросите в комментариях, но так как вы учитесь, я хочу, чтобы вы попробовать самостоятельно.

1 голос
/ 31 марта 2020
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/

1 голос
/ 30 марта 2020

Вы не должны иметь функции, объявленные внутри рендера. Переместите их в класс и пропустите префикс «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>
...