I'm new to react and I've tried to fetch data using "setData" and then using the state variable "data" to set the values of title , desc and author but I'm getting them as undefined. After setting the initial states to empty I've set the values of the input fields to what I had got from the "data" state and when I submit the form only the fields in which the changes are made were updated the rest of the fields had "undefined" values i.e when I submitted the form to update it looked like this {title:undefined,desc:undefined,author:"person1"}, I'm unable to set the initial state values to input field values.
EditBlog.js
import React, { useState, useEffect } from "react"
import { useParams, useHistory } from "react-router-dom"
const EditBlog = () => {
const { id } = useParams()
useEffect(() => {
fetch('http://localhost:8000/values/' id)
.then((res) => {
return res.json()
})
.then((data) => {
setData(data)
})
}, [id])
const [data, setData] = useState({})
const [title, setEditTitle] = useState()
const [desc, setEditDesc] = useState()
const [author, setEditAuthor] = useState()
const history = useHistory()
const updateHandler = (e) => {
e.preventDefault()
const updatedBlog = { title, desc, author }
fetch('http://localhost:8000/values/' id, {
method: "PUT",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(updatedBlog)
})
.then(() => {
console.log(updatedBlog)
history.push("/")
})
}
return (
<React.Fragment>
<div>
<h1>Edit Blog</h1>
<form onSubmit={updateHandler} className="new-blog">
<label>Blog Title</label>
<div className="input-box">
<input
onChange={(e) => setEditTitle(e.target.value)}
type="text"
defaultValue={data.title}
className="inputField"
/>
</div>
<label>Blog Body</label>
<div className="input-box">
<textarea
onChange={(e) => setEditDesc(e.target.value)}
cols="64"
defaultValue={data.desc}
/>
</div>
<label>Blog Author</label>
<div className="input-box">
<input
onChange={(e) => setEditAuthor(e.target.value)}
className="inputField"
type="text"
defaultValue={data.author}
/>
</div>
<button>Save</button>
</form>
</div>
</React.Fragment>
)
}
export default EditBlog
CodePudding user response:
You're confusing yourself by trying to keep two copies of the same data in state. Reduce the state to just the one object you're editing (and give it initial values for the inputs, so nothing is undefined
):
const [data, setData] = useState({
title: '',
desc: '',
author: ''
});
Have your inputs use and update the values in that state object:
<input
onChange={(e) => setData({...data, title: e.target.value})}
type="text"
value={data.title}
className="inputField"
/>
Note the use of value={data.title}
so the input always shows the current value, and the new onChange
which updates the same state being used and just changes the one value in that state object.
Then when you post the form, simply post the current state instead of building a new object from separately tracked values:
body: JSON.stringify(data)
In short, you don't need or want these:
const [title, setEditTitle] = useState()
const [desc, setEditDesc] = useState()
const [author, setEditAuthor] = useState()
Because you already have your data in data
.
CodePudding user response:
In useEffect
add this code in .then
block after setData(data)
:
setEditTitle(data.title)
setEditDesc(data.description)
setEditAuthor(data.author)
And replace defaultValue={data.title}
with value={title}
and the other two in the same way.
Note: I would say that The best approach is to avoid using states
for your fields as you are already saving the state
in useData
. You should modify your code to avoid having three different state
hooks.