I'm a newbie to React.js and I face with a strange error that I can't figure out why that's happening, I searched but and didn't find any solutions.
Here is is my component codes:
import React, { useState } from "react";
const AddMovie = () => {
const [movie, setMovie] = useState({ title: "", director: "" });
const onChange = (value, filed) => {
setMovie({
[filed]: value,
});
};
const onSubmit = (e) => {
e.preventDefault();
console.log(movie.title, movie.director);
setMovie({ title: "", director: "" });
};
return (
<div>
<form className="flex -mx-2" onSubmit={onSubmit}>
<div className="ml-2">
<input
type="text"
className="border p-2 rounded-md focus:outline-none"
placeholder="Movie Title"
value={movie.title}
onChange={(e) => onChange(e.target.value, "title")}
required
/>
</div>
<div className="mx-2">
<input
type="text"
className="border p-2 rounded-md focus:outline-none"
placeholder="director"
value={movie.director}
onChange={(e) => onChange(e.target.value, "director")}
required
/>
</div>
<div>
<button
type="submit"
className="h-full border rounded-md px-4 text-white bg-gray-900"
>
Add Movie
</button>
</div>
</form>
</div>
);
};
export default AddMovie;
and the error that I face with it is this: (i referred to DOC and I read this section but it didn't work as well)
react_devtools_backend.js:3973 Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
so what is the problem?
I have done this way of binding (object syntax) in Vue.js
a lot of times but I haven't been facing this once, so is a bit queer for me.
CodePudding user response:
The error is due to value={movie.director}
being undefined
once you change your movie title. That happens because you miss use the setter API,
With hooks (READ THE NOTE), the state setter does not merge state as in class component, change it to:
// field = 'title'
setMovie(prevState => ({...prevState, [field]: value }))
Unlike the setState method found in class components, useState does not automatically merge update objects.
Unlike the setState method found in class components, useState does not automatically merge update objects.