Reputation: 151
I'm getting a really weird return error that on submission I randomly add an extra duplicate field somehow which is of course then undefined. The input value is also randomly copied from one of the other fields within the form.
const GameForm = () => {
const url = 'http://localhost:6060/games'
const handleInputChange = e => {
const { name, value, year, rating, developer } = e.target
setGameData({ ...gameData, [name]: value, [year]: value, [rating]: value, [developer]: value })
}
const onSubmit = (e) => {
e.preventDefault()
const { name, year, rating, developer } = gameData
if (!name || !year || !rating || !developer) return
console.log(gameData)
axios
.post(url, gameData)
.then((res) => {
setGameData(res)
}).catch((error) => console.log(error))
}
const [gameData, setGameData] = useState({ name: '', year: 0, rating: '', developer: "" })
return (
<form onSubmit={onSubmit}>
<label id="name" htmlFor="name">Name: </label>
<input type="text" name="name" placeholder="Game title" onChange={handleInputChange} />
<br />
<label htmlFor="year">Year: </label>
<input type="number" name="year" placeholder="Release year" onChange={handleInputChange} />
<br />
<label htmlFor="rating">Rating: </label>
<input type="text" name="rating" placeholder="Age rating" onChange={handleInputChange} />
<br />
<label htmlFor="developer">Developer: </label>
<input type="text" name="developer" placeholder="Developer" onChange={handleInputChange} />
<br />
<input type="submit" value="Submit"></input>
</form>
)
}
Console logged return: (I also get a 500 error obviously)
{name: "1", year: "1", rating: "1", developer: "1", undefined: "1"}
The undefined value is seemingly taken from any of the existing fields at random.
I feel like I am likely overlooking something obvious.
Upvotes: 0
Views: 390
Reputation: 7460
You are mis-using e.target
. It will not have all the properties that you try to destruct from it. From the ones you list in your example code, it will only have name
and value
, all the other ones (rating, year, developer) will be undefined
as they are not part of the event's target property.
The reason you only get one undefined
value in your state object is because it keeps overriding itself when you set your state.
The property from the event target you are trying to access is name
, so in your case basically e.target.name
Anyway, with that in mind the fix for your app will be quite simple:
const handleInputChange = e => {
const { name, value } = e.target
// Note: The name will hold whatever value of the name prop you put on your input.
// When you are editing the input with the name prop set to name, it will be "name"
// For the input with the name prop set to "year", it will be "year:
// For the input with the name prop set to "developer" it will be "developer" and so on.
setGameData({ ...gameData, [name]: value })
}
Here is a demo for you with the fix:
const App = () => {
const [gameData, setGameData] = React.useState({ name: '', year: 0, rating: '', developer: "" })
const handleInputChange = e => {
const { name, value } = e.target
setGameData({ ...gameData, [name]: value })
}
return (
<div>
<label id="name" htmlFor="name">Name: </label>
<input type="text" name="name" placeholder="Game title" onChange={handleInputChange} />
<br />
<label htmlFor="year">Year: </label>
<input type="number" name="year" placeholder="Release year" onChange={handleInputChange} />
<br />
<label htmlFor="rating">Rating: </label>
<input type="text" name="rating" placeholder="Age rating" onChange={handleInputChange} />
<br />
<label htmlFor="developer">Developer: </label>
<input type="text" name="developer" placeholder="Developer" onChange={handleInputChange} />
<br />
<button onClick={() => console.warn('GAME DATA OBJECT', gameData)}>Click</button>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Upvotes: 1