Reputation: 115
const [product, setProduct] = useState({
productName: "",
quantity: 0,
basePrice: 0,
sellPrice: 0,
})
const handleChange = (e) => {
let fieldName = e.target.id;
let fieldValue = e.target.value;
setProduct({
fieldName: fieldValue
});
};
Code above doesnt seem to work. when i log fieldName however, it return productName
.
I tried to explicitly use productName instead and its working
const handleChange = (e) => {
let fieldName = e.target.id;
let fieldValue = e.target.value;
setProduct({
productName: fieldValue
});
}
Can anyone tell me whats going on under the hood why the initial approach is not working?
PS reason i want to use e.target.id is because there are multiple fields that needs updating Thank you
Upvotes: 2
Views: 201
Reputation: 1624
React hooks works differently than the classic setState .
In setState, even if you set the one property and never mention the other properties, those properties will persist. e.g For state of name and email, if you do the setState for name, email value will be there, it won't be erased.
But in useState, the value won't be there. Similar to the previous example, if you set the name property, email will be erased i.e undefined. So either you can spread the old object to get the old values Or you can create separate states for individuals (e.g useState for name and useState for email)
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [store, setStore] = useState({
name: "",
email: ""
});
const handleChange = (e) => {
// console.log(e, e.target.name, e.target.value);
setStore({...store, [e.target.name]: e.target.value }); // Spreading
};
return (
<div className="App">
<label id="name">Name</label>
<input
name="name"
type="text"
htmlFor="name"
value={store.name}
onChange={handleChange}
></input>
<br />
<br />
<label id="email">email</label>
<input
name="email"
type="text"
htmlFor="email"
value={store.email}
onChange={handleChange}
></input>
</div>
);
}
Another way
const [name, setName] = useState("");
const [email,setEmail]= useState("");
// handle the change handlers
Upvotes: 1
Reputation: 39432
The setter on the useState
doesn't work like the setState
method on a React Class Component.
Setting just a particular field name would override the values of the other fields in the product
Object and will set them to undefined
.
You'll have to spread the existing product
Object to get the values of the other fields and then only override the value of the field by using the []
notation to dynamically set the field name.
Something like this:
setProduct({
...product,
[fieldName]: fieldValue
});
Upvotes: 3