I'm new to React and have run into a problem building a simple form component. There are four input fields and four matching onChange handlers. All of them are effectively identical:
handleEmailChange(event) {
this.setState({email: event.target.value});
}
handlePasswordChange(event) {
this.setState({password: event.target.value});
}
handleFirstNameChange(event) {
this.setState({firstName: event.target.value});
}
handleLastNameChange(event) {
this.setState({lastName: event.target.value});
}
render() {
return (
<div>
<label>Email: </label>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<label>Password: </label>
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
<label>First name: </label>
<input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
<label>Last name: </label>
<input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
<input type="submit" value="Add User" onClick={this.handleSubmit} />
</div>
)
}
Three of these work just fine. The password handler, however, throws a TypeError exception "event.target is undefined" when the page tries to render. If I remove the handler and input element, the app renders. If I copy and paste one of the other handlers and inputs and change the relevant names, it still throws the exception. If I change the input type from "password" to "text" it still throws the exception. I cannot figure out why a seemingly identical piece of code is throwing this exception but every other piece of code like it works just fine.
In case it matters, the code for the entire component is
class AddUserForm extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
firstName: '',
lastName: ''
};
this.validate = this.validate.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange(this);
this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
this.handleLastNameChange = this.handleLastNameChange.bind(this);
}
validate(user) {
return (user.email && user.password && user.firstName && user.lastName);
}
handleSubmit(event) {
let newUser = {
email: this.state.email,
password: this.state.password,
firstName: this.state.firstName,
lastName: this.state.lastName
};
if (AddUserForm.validate(newUser)) {
fetch(`http://localhost:3001/admin/addUser`, {
method: 'post',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
}),
body: JSON.stringify(newUser)
})
.then( res => {
const copy = [newUser].concat(this.state.users);
this.setState({users: copy});
})
}
event.preventDefault();
}
handleEmailChange(event) {
this.setState({email: event.target.value});
}
handlePasswordChange(event) {
this.setState({password: event.target.value});
}
handleFirstNameChange(event) {
this.setState({firstName: event.target.value});
}
handleLastNameChange(event) {
this.setState({lastName: event.target.value});
}
render() {
return (
<div>
<label>Email: </label>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<label>Password: </label>
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
<label>First name: </label>
<input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
<label>Last name: </label>
<input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
<input type="submit" value="Add User" onClick={this.handleSubmit} />
</div>
)
}
}
You are invoking handlePasswordChange in the constructor by writing handlePasswordChange(this). You want to bind it to this instead.
this.handlePasswordChange = this.handlePasswordChange.bind(this);
Related
Currently, i have this state with a formData.
Upon typing some text, instead to change the fullName.firstName. its making another property and just setting a single (as in single letter) value.
const [formData, setFormData] = useState({
fullName: {
firstName: "",
lastName: "",
},
email: "",
password: "",
confirmPassword: "",
});
This is how i set the formData.
const handleChange = (event) => {
const { value, name } = event.target;
console.log(name, value);
setFormData((prevFormData) => ({
...prevFormData,
[name]: value,
}));
};
This is my JSX, you may check the "name" attribute in input for some reference.
<div className="App">
<form onSubmit={onSubmit}>
<h1>Submit Form Nested Object UseState</h1>
<input
text="text"
placeholder="First Name"
name="firstName"
value={formData.fullName.firstName}
onChange={handleChange}
/>
<input
text="text"
placeholder="Last Name"
name="lastName"
value={formData.fullName.lastName}
onChange={handleChange}
/>
<input
text="email"
placeholder="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
<input
text="password"
placeholder="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
<input
text="password"
placeholder="confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
/>
<button>Submit</button>
</form>
{JSON.stringify(formData, null, 2)}
</div>
Change the form names like so:
<form onSubmit={onSubmit}>
<h1>Submit Form Nested Object UseState</h1>
<input
placeholder="First Name"
name="fullName.firstName"
value={formData.fullName.firstName}
onChange={handleChange}
/>
<input
placeholder="Last Name"
name="fullName.lastName"
value={formData.fullName.lastName}
onChange={handleChange}
/>
<input
placeholder="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
<input
placeholder="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
<input
placeholder="confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
/>
<button>Submit</button>
</form>
then change your handleChange function to this:
const handleChange = (event) => {
const { value } = event.target;
const [key,subkey] = event.target.name.split('.');
setFormData((prevFormData) => ({
...prevFormData,
[key]: subkey ? {
...prevFormData[key],
[subkey]: value,
} : value
}));
};
I am trying to create a payment system in my application.
I have a payment form(paymentForm.js) and it contains the payment information(cardnumber, cvv, expiry...). Is there any way that I can get these information on another component(checkoutPage.js)? Do you have any advice?
Below is my paymentForm.js:
export default class PaymentForm extends React.Component {
state = {
cvv: '',
expiry: '',
focus: '',
name: '',
number: '',
};
handleInputFocus = (e) => {
this.setState({ focus: e.target.name });
}
handleInputChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
}
render() {
return (
<View>
<Cards id="PaymentForm"
cvc={this.state.cvc}
expiry={this.state.expiry}
focused={this.state.focus}
name={this.state.name}
number={this.state.number}
/>
<form style={{}}>
<input
type="tel"
name="number"
placeholder="Card Details"
maxLength="16"
preview='true'
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="text"
name="name"
placeholder="Holder Name"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="expiry"
placeholder="Expiration"
maxLength="4"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="cvc"
placeholder="CVV"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="zipcode"
placeholder="ZIP Code"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
</form>
</View>
);
}
}
You should create a file CheckOut.js and give card information via props. There is also another way to do it by creating a class named 'Checkout' and creating static methods inside.
I'm new to react, and I've done a Form which I want to come up an alert when clicking the submit button. When I opened it on a browser through my local file it worked but when seeing on GitHub I don't get the same result, not sure why. I save it and push it to the repository.
Here it's how it looks https://joanaoli09.github.io/milestone/
Here is the code to the Form.js file:
import React from "react";
import "./Form.css";
export default class Form extends React.Component {
state = {
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
};
onSubmit = e => {
alert("Your information has been uploaded");
e.preventDefault();
this.props.onSubmit(this.state);
this.setState({
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
});
};
render() {
return (
<div className="formcontainer">
<form className="Form">
<p className="register">CREATE ACCOUNT</p>
<input
className="input"
name="firstName"
placeholder="First name"
value={this.state.firstName}
onChange={e => this.change(e)}
/>
<br />
<input
className="input"
name="lastName"
placeholder="Last name"
value={this.state.lastName}
onChange={e => this.change(e)}
/>
<br />
<input
className="input"
name="username"
placeholder="Username"
value={this.state.username}
onChange={e => this.change(e)}
/>
<br />
<input
className="input"
name="email"
placeholder="Email"
value={this.state.email}
onChange={e => this.change(e)}
/>
<br />
<input
className="input"
name="password"
type="password"
placeholder="Password"
value={this.state.password}
onChange={e => this.change(e)}
/>
<br />
<button className="submit" onClick={e => this.onSubmit(e)}>
Submit
</button>
</form>
</div>
);
}
}
If you inspect the Form.js file on that URL, you will see this:
onSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.state);
this.setState({
firstName: "",
lastName: "",
userName: "",
email: "",
password: ""
});
};
So it looks like what you have deployed to that URL and what you have posted here is not the same. You might have pushed some new code to your repo, but if the changes are not appearing on that URL, you might have forgotten to deploy them again or the deploy pipeline might have failed for some reason.
The code here is missing some bits like the onChange callback, but adding them back it works just fine:
const App = () => {
const [state, setState] = React.useState({
firstName: '',
lastName: '',
username: '',
email: '',
password: '',
});
const handleSubmit = React.useCallback((e) => {
alert('Your information has been uploaded.');
e.preventDefault();
setState({
firstName: '',
lastName: '',
username: '',
email: '',
password: '',
});
}, []);
const handleChange = React.useCallback(({ target }) => {
setState((prevState) => ({ ...prevState, [target.name]: target.value }));
}, []);
return (
<div className="formcontainer">
<form className="Form">
<p className="register">CREATE ACCOUNT</p>
<input
className="input"
name="firstName"
placeholder="First name"
value={ state.firstName }
onChange={ handleChange }
/>
<input
className="input"
name="lastName"
placeholder="Last name"
value={ state.lastName }
onChange={ handleChange }
/>
<input
className="input"
name="username"
placeholder="Username"
value={ state.username }
onChange={ handleChange }
/>
<input
className="input"
name="email"
placeholder="Email"
value={ state.email }
onChange={ handleChange }
/>
<input
className="input"
name="password"
type="password"
placeholder="Password"
value={ state.password }
onChange={ handleChange }
/>
<button className="submit" onClick={ handleSubmit }>
Submit
</button>
</form>
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
body {
font-family: monospace;
}
.input,
.submit {
display: block;
margin-bottom: 8px;
font-family: monospace;
padding: 8px;
background: white;
border: 2px solid black;
}
<script src="https://unpkg.com/react#16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
I think there are some issues in your code here
<input
className="input"
name="username"
placeholder="Username"
value={this.state.username}
onChange={()=>this.change(e)}
/>
Here instead of name="username" it should be name="userName" because in
change = e => {
this.setState({
[e.target.name]: e.target.value //you are passing [e.target.name]
});};
And please make sure you always deploy the code again after making any changes in the repo by running npm run deploy
This is my jsx for the form
import React, { Component } from "react";
import { createUser } from "../HTTPRequests";
import PhoneInput from "react-phone-number-input";
class UserRegForm extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
secondPassword: "",
username: "",
phone: "",
current: 0
};
this.handleEmail = this.handleEmail.bind(this);
this.handlePassword = this.handlePassword.bind(this);
this.handleSecondPassword = this.handleSecondPassword.bind(this);
this.handleUsername = this.handleUsername.bind(this);
this.renderSecondPassword = this.renderSecondPassword.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handlePhone = this.handlePhone.bind(this);
}
handleEmail(event) {
this.setState({ email: event.target.value });
}
handlePassword(event) {
this.setState({ password: event.target.value });
}
handleSecondPassword(event) {
this.setState({ secondPassword: event.target.value });
}
handleUsername(event) {
this.setState({ username: event.target.value });
}
handlePhone(phone) {
this.setState({ phone: phone.value });
}
renderSecondPassword() {
var classN;
if (
this.state.secondPassword.length === 0 ||
this.state.secondPassword === this.state.password
) {
classN = "form-control";
} else {
classN = "form-control is-invalid";
}
return (
<div className="form-group">
<label htmlFor="InputPassword2">Introduza novamente a Password</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleSecondPassword}
type="password"
className={classN}
id="InputPassword2"
/>
</div>
);
}
handleKeyDown(event) {
if (event.key === "Enter") {
this.handleSubmit();
}
}
handleSubmit() {
createUser(this.state.email, this.state.password, this.state.username).then(
function(r) {
console.log(r);
}
);
}
render() {
return (
<div className="position-relative m-4">
<form>
<div className="form-group">
<label htmlFor="exampleInputUsername">Nome Completo</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleUsername}
type="username"
className="form-control"
id="exampleInputUsername"
/>
</div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">E-mail</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleEmail}
type="email"
className="form-control"
id="exampleInputEmail1"
aria-describedby="emailHelp"
/>
<small id="emailHelp" className="form-text text-muted">
Nunca partilharemos o seu e-mail com ninguém.
</small>
</div>
<PhoneInput
placeholder="Enter phone number"
value={this.state.phone}
onChange={phone => this.handlePhone({ phone })}
/>
<div className="form-group">
<label htmlFor="InputPassword1">Password</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handlePassword}
type="password"
className="form-control"
id="InputPassword1"
/>
</div>
{this.renderSecondPassword()}
<button
type="button"
className="btn btn-primary"
onClick={this.handleSubmit}
>
Submit
</button>
</form>
</div>
);
}
}
export default UserRegForm;
And this is the result...
as you can see the flag just expands to the whole screen.
I have programming experience (C and java), but just started learning HTML and React... So i'm still a bit lost. do I have to wrap the phone number component in something so it behaves? According to documentation the flag should be to the left of the input and not below
Any help is very appreciated
As someone who just encountered the same issue as OP after an update, the fix was very simple:
import 'react-phone-number-input/style.css'
According to last version of the docs : https://github.com/catamphetamine/react-phone-number-input
I am creating a simple login page. When I declared states and tried to use them in input field's value, I am unable to enter or type anything in the input box.
This problem is occurring only with password input box, email input box is working fine.
export default class SignIn extends Component{
constructor(props){
super(props)
this.state = {
email:'',
password:''
};
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleEmailChange(event) {
this.setState({email: event.target.value});
console.log(this.state.email)
}
handlePasswordChange(event) {
this.setState({Password: event.target.value});
console.log(this.state.password)
}
handleSubmit(event) {
event.preventDefault();
const fdata = new FormData()
fdata.append('email',this.state.email)
fdata.append('password',this.state.password)
axios({
method: 'post',
url: 'abc.com/abc',
data: fdata
})
.then(function(response){
console.log(response)
response.json()
})
.then(function(responseJson){
console.log(responseJson)
})
.catch(function(){
alert("Failed")
})
}
render(){
return(
<div>
<div className="container mt-5">
<form action="/action_page.php">
<div className="form-group">
<label htmlFor="email">Email:</label>
<input type="email"
value={this.state.email}
onChange={this.handleEmailChange}
className="form-control"
id="email"
placeholder="Enter email"
name="email" />
</div>
<div className="form-group">
<label htmlFor="pwd">Password:</label>
<input type="password"
value={this.state.password}
onChange={this.handlePasswordChange}
className="form-control"
id="pwd"
placeholder="Enter password"
name="pswd" />
</div>
<button type="submit" onClick={this.handleSubmit}>Submit</button>
</form>
</div>
</div>
)
}
}
I expect to use password state in input type password, and don't want to use any default value.
change Password to password in setState
your code
handlePasswordChange(event) {
this.setState({Password: event.target.value});
console.log(this.state.password)
}
new code
handlePasswordChange(event) {
this.setState({password: event.target.value});
console.log(this.state.password)
}
You have a typo in your function:
handlePasswordChange(event) {
this.setState({Password: event.target.value});
// should be
this.setState({password: event.target.value});
console.log(this.state.
}