Home > front end >  How to set the initial state value after fetching data to update a form in react
How to set the initial state value after fetching data to update a form in react

Time:09-22

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.

  • Related