React中fetch获取数据后如何设置初始state值来更新表单?
问题根因
- 你用了
defaultValue实现非受控输入框,这个属性只在组件首次渲染时生效,你的接口请求是组件渲染后才触发的,拿到数据后defaultValue不会更新,所以未手动修改的字段对应的状态一直是初始的undefined。 - 同时你维护了两套冗余状态:
data存储接口返回的原始数据,单独的title/desc/author存储表单值,两者没有做同步,未修改的字段状态一直停留在初始的空值。
修复方案
直接复用data作为表单的受控状态,不需要单独维护三个字段的状态,修改后代码如下:
import React, { useState, useEffect } from "react" import { useParams, useHistory } from "react-router-dom" const EditBlog = () => { const { id } = useParams() const history = useHistory() // 初始化状态对应字段,避免首次渲染报undefined错 const [data, setData] = useState({ title: "", desc: "", author: "" }) useEffect(() => { fetch('http://localhost:8000/values/' + id) .then((res) => res.json()) .then((resData) => { setData(resData) }) }, [id]) const updateHandler = (e) => { e.preventDefault() const updatedBlog = { title: data.title, desc: data.desc, author: data.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("/") }) } // 统一处理输入框变更,减少重复代码 const handleInputChange = (field) => (e) => { setData(prev => ({ ...prev, [field]: e.target.value })) } return ( <React.Fragment> <div> <h1>Edit Blog</h1> <form onSubmit={updateHandler} className="new-blog"> <label>Blog Title</label> <div className="input-box"> <input onChange={handleInputChange('title')} type="text" value={data.title} className="inputField" /> </div> <label>Blog Body</label> <div className="input-box"> <textarea onChange={handleInputChange('desc')} cols="64" value={data.desc} /> </div> <label>Blog Author</label> <div className="input-box"> <input onChange={handleInputChange('author')} className="inputField" type="text" value={data.author} /> </div> <button>Save</button> </form> </div> </React.Fragment> ) } export default EditBlog
修改说明
- 给
data状态初始化了对应字段的空值,避免组件首次渲染时输入框value为undefined的报错 - 把原来的非受控输入框改成受控输入框,用
value绑定data对应字段,接口返回数据后会自动同步填充到输入框 - 新增了通用的
handleInputChange方法处理所有输入框的变更,减少重复代码 - 提交时直接从
data取所有字段值,未修改的字段也会保留接口返回的初始值,不会出现undefined的问题
内容的提问来源于stack exchange,提问作者UN_1032
相关产品推荐
相关产品推荐

