无法读取未定义的属性状态
我尝试从表单中获取用户的输入,然后提交该信息,并发出警报,显示用户在正式提交表单之前输入的内容。但是,我不知道如何解决状态未定义的问题。我最初在类组件之外使用了 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);```
您不应该在 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>
为什么
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;
}
}
在这里,您所做的是,在
render()
内创建了一个全新的函数
FormCreate()
。虽然永远不应该这样做,但我们假设在我们的例子中可以这样做。
错误是在
FormCreate()
中的
value: this.state.value
行处引发的。这是因为
FormCreate()
中的
this
引用的是
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()
之外。并且,永远不要忘记在
render()
方法中返回 React Element 或
null
。
如果您想要完整的代码,请在评论中提问,但由于您正在学习,我希望您自己尝试一下。
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/