I am building a simple blog app and I am trying to update title
of the blog But it is not updating, it is just showing the current state.
I have tried many times by changing the method of setting state but it is still showing that error.
App.js
function BlogDetail() {
const [blogName, setBlogName] = useState("");
axios.get("/api/blog_detail/70/").then(res => {
setBlogName(res.data[0].blog_name)
})
const handleChange = (e) => {
console.log(e.target.value)
setBlogName({
...blogName,
[e.target.name]: e.target.value
})
}
const saveBlog = (e) => {
// sending to API
console.log(blogName)
}
return (
<div>
<form>
{blogName}
<input type="text" name="blogName" value={blogName} onChange={e => handleChange} />
<button type="submit" onClick={e => saveBlog(e)}>Save</button>
<form>
</div>
)
}
And When I update on change instead of updating on submit
onChange=(e => setBlogName(e.target.value))
Then it is showing
A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined
I have tried many times but it is still not working.
CodePudding user response:
input
requires a string as a value, but you are trying to pass an object:
setBlogName({
...blogName,
[e.target.name]: e.target.value
})
instead pass a string:
setBlogName(e.target.value)
Also, you need to execute handleChange
function and pass the event
param.
onChange={e => handleChange(e)}
Edit:
Looked at it second time and it should be like this:
function BlogDetail() {
const [blogName, setBlogName] = useState("");
// without this you override state every time you press a key
useEffect(() => {
axios.get("/api/blog_detail/70/").then(res => {
setBlogName(res.data[0].blog_name)
})
}, [])
const handleChange = (e) => {
// just use value here
setBlogName(e.target.value)
}
const saveBlog = (e) => {
// sending to API
console.log(blogName)
}
return (
<div>
<form>
{blogName}
{ /* remember to run the function */ }
<input type="text" name="blogName" value={blogName} onChange={e => handleChange()} />
<button type="submit" onClick={e => saveBlog(e)}>Save</button>
<form>
</div>
)
}
CodePudding user response:
Besides the problem that within handleChange
you need to pass an an string value to setBlogName
you also need to wrap your axios fetch call in a useEffect
.
The problem is that everytime you trigger a rerender while calling setBlogName
you are calling your API point again and set the value back to the fetched value.
You should prevent that by doing the following ->
useEffect(() => {
axios.get("/api/blog_detail/70/").then(res => {
setBlogName(res.data[0].blog_name)
}), [])
Don't forget to install { useEffect } from 'react'
.
And well of course update handleChange
->
const handleChange = (e) => {
const newBlogPostName = e.target.value
console.log(newBlogPostName)
setBlogName(newBlogPostName)
}
CodePudding user response:
you have not any action in this method. where is the update state?
const saveBlog = (e) => {
// sending to API
console.log(blogName)
}
and in this method you change the string to an object
const handleChange = (e) => {
console.log(e.target.value)
setBlogName({
...blogName,
[e.target.name]: e.target.value
})
}
CodePudding user response:
so the problem is that your function updates your state to an object and then you want to display that object(not a string property of that object) in the DOM
. its wrong because you cant display objects in the DOM
in react. in this case, you even get an error because you cant use spread operator
on strings
. you cant do something like this: ...("test")
const handleChange = (e) => {
console.log(e.target.value)
//the state value will be an object. its wrong. you even get an error
because of using spread operator on a string
setBlogName({
...blogName //this is a string at the init time,
[e.target.name]: e.target.value
})
}
so whats the solution? you should update your state to a string or use a string property of the object. something like this:
const handleChange = (e) => {
console.log(e.target.value)
setBlogName("string")
}
return (<>{blogName}</>)
thats it.