I read about using a single handler for multiple input fields. When I'm trying to use that approach -> using event.target.value
, I am getting just the first letter of what I entered in the input. Can anyone please help me on what I am doing wrong.
class AddContactForm extends Component {
constructor(props) {
super(props);
this.name = "";
this.email = ""
this.phone = "";
}
componentDidUpdate() {
console.log("updated");
}
componentWillUnmount() {
console.log("unmounted");
}
componentWillMount() {
console.log("mounted");
}
handleOnChange(event) {
[event.target.name] = event.target.value;
console.log(event)
console.log(event.target.name);
console.log(event.target.value);
}
addContact() {
console.log("add");
this.props.addContactHandler({
name: this.name,
email: this.email,
phone: this.phone
});
}
render() {
return (
<React.Fragment>
<div className="mx-auto">
<div class="mb-3 row">
<label for="username" class="col-sm-2 col-form-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name='name' id="username" onChange={this.handleOnChange.bind(this)} />
</div>
</div>
<div class="mb-3 row">
<label for="mobileNumber" class="col-sm-2 col-form-label">Mobile Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="phone" id="mobileNumber" onChange={this.handleOnChange.bind(this)} />
</div>
</div>
<div class="mb-3 row">
<label for="emailId" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="emailId" name="email" onChange={this.handleOnChange.bind(this)} />
</div>
</div>
<button className="btn btn-primary w-25" onClick={this.addContact.bind(this)}>Add</button>
</div>
</React.Fragment>
)
}
}
export default AddContactForm;
inside handle on change, the value of [event.target.name] always shows whatever was my first input alphabet. for If I am writong abcd ing input, ikt'll keep showing me a .
Where am I going wrong ?
CodePudding user response:
You haven't set the state properly in both constructor
and handleChange
functions.
Try this
import React, { Component } from "react";
class AddContactForm extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
phone: ""
};
}
componentDidUpdate() {
console.log("updated");
}
componentWillUnmount() {
console.log("unmounted");
}
componentWillMount() {
console.log("mounted");
}
handleOnChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
addContact() {
console.log("add");
console.log(this.state);
// this.props.addContactHandler(this.state);
}
render() {
return (
<React.Fragment>
<div className="mx-auto">
<div class="mb-3 row">
<label for="username" class="col-sm-2 col-form-label">
Name
</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
name="name"
id="username"
onChange={this.handleOnChange.bind(this)}
/>
</div>
</div>
<div class="mb-3 row">
<label for="mobileNumber" class="col-sm-2 col-form-label">
Mobile Number
</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
name="phone"
id="mobileNumber"
onChange={this.handleOnChange.bind(this)}
/>
</div>
</div>
<div class="mb-3 row">
<label for="emailId" class="col-sm-2 col-form-label">
Email
</label>
<div class="col-sm-10">
<input
type="email"
class="form-control"
id="emailId"
name="email"
onChange={this.handleOnChange.bind(this)}
/>
</div>
</div>
<button
className="btn btn-primary w-25"
onClick={this.addContact.bind(this)}
>
Add
</button>
</div>
</React.Fragment>
);
}
}
export default AddContactForm;
If all of your fields are identical, you can even dynamically render them by mapping over the keys of the state object:
class AddContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
phone: ""
};
}
handleOnChange = (event) => {
const { name, value } = event.target;
this.setState({
[name]: value
});
};
render() {
return (
<React.Fragment>
{Object.keys(this.state).map((key) => (
<label>
{key}
<input
type="text"
name={key}
onChange={this.handleOnChange}
value={this.state[key]}
/>
</label>
))}
<pre>{JSON.stringify(this.state, null, 2)}</pre>
</React.Fragment>
);
}
}
export default AddContactForm;
CodePudding user response:
The issue is with the first line of code in this function.
handleOnChange(event) {
[event.target.name] = event.target.value;
console.log(event)
console.log(event.target.name);
console.log(event.target.value);
}
That changes the HTML Input element name
's first letter to the first letter of the input value
you have typed.
Add with the following log
handleOnChange = (event) => {
[event.target.name] = event.target.value;
console.log(event);
console.log(event.target);
console.log(event.target.name);
console.log(event.target.value);
};
Solution
To change the class variable dynamically, instead of
[event.target.name] = event.target.value;
use
this[event.target.name] = event.target.value;