Reputation: 37
I am trying to take input from a user in a form and then submit that information with an alert that shows what the user entered into the form before officially submitting it. However, I cannot figure out how to get solve the issue of state undefined. I initially had the FormCreate and FormDisplay function outside of the class component but still had the same error. After reading for several hours I put them inside the function but still get the same issue.
What am I missing?
'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);```
Upvotes: 0
Views: 496
Reputation: 56
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
I changed a few things around, but this is what you are going for I believe. The only thing you will need to fix is displaying the users information.
Every keystroke from the user causes a redraw of every input element, instead of only the element the user is typing in. It works, but seems inefficient. If it is by a design that I am not seeing, so be it. A simply observation.
Take the time and read through the React documentation, once it clicks React is aweseome. https://reactjs.org/
Check out this information as well, it helped me when I was putting together a form element https://www.taniarascia.com/getting-started-with-react/
Upvotes: 1
Reputation: 3604
this.state
is undefined
?For that let's look at the render()
of yours where it lies, shall we?
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;
}
}
Here what you did was, you created a brand new function FormCreate()
inside render()
. Though it should never be done, we'll assume it can be in our case.
The error was thrown at the line value: this.state.value
inside FormCreate()
. This is because the this
inside FormCreate()
is refering to the FormCreate
itself and not our React component, which in here is FormFind
.
NOTE: FormCreate
is different from FormCreate()
.
Since FormCreate
doesn't have state
key inside, this.state
(or FormCreate.state
) is undefined
. That is exactly why you were getting the error.
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;
}
}
Extract FormCreate()
as method and put it outside render()
. And don't ever forget to return a React Element or null
in the render()
method.
If you want the full code, ask in the comments, but since you're learning, I want you to try by yourself.
Upvotes: 1
Reputation: 1720
You shouldn't have the functions declared inside render. Move them inside the class and skip the "function"-prefix so that they belong to your class.
Then change all references to them to this.FormCreate for example.
Besides that I changed the way you set state to the inputs name, like this:
this.setState({
[e.target.name]: e.target.value
}),
Here's your code but with the fixes implemented:
'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>
Upvotes: 1