如何将useEffect从Firestore获取的数据设置为TextField的初始值?
现有代码存在的问题
- 从Firestore拉取到用户原始数据后,没有同步给表单对应的state变量,未修改的字段state默认是空字符串,提交时会将空值写入数据库
- 输入框
value绑定的是拉取到的静态用户数据而非对应state,修改输入内容时页面不会同步更新 - 单用户编辑场景不需要用数组存储用户数据、循环渲染表单,冗余逻辑增加出错概率
useEffect依赖数组为空,若路由传递的uid发生变化,不会重新拉取对应新用户的数据
修正后的完整代码
import { useState, useEffect } from 'react' // 其余原有引入(firestore、TextField、CardHeader、Button等)保持不变 const Edit = () => { const uid = location.state; const [isLoading, setIsLoading] = useState(false); // 移除冗余的users数组,直接存储单用户对象,同时声明所有表单字段的state const [user, setUser] = useState(null); const [firstName, setFirstName] = useState(""); const [middleName, setMiddleName] = useState(""); const [lastName, setLastName] = useState(""); const [address, setAddress] = useState(""); useEffect(() => { if(!uid) return const unsubscribe = firestore .collection("users") .doc(uid) .onSnapshot((snapshot) => { if(snapshot.exists) { const userData = snapshot.data() setUser(userData) // 拉取到数据后同步给所有表单state作为初始值 setFirstName(userData.firstName || "") setMiddleName(userData.middleName || "") setLastName(userData.lastName || "") setAddress(userData.address || "") setIsLoading(true); } }); return () => { unsubscribe(); }; // 依赖数组新增uid,uid变化时自动重新拉取对应用户数据 }, [uid]); const handleSubmit = async (e) => { e.preventDefault(); try { const userRef = firestore.collection("users").doc(uid); // 所有字段从state取值,未修改的字段也保留了初始原始值,不会为空 await userRef.set( { firstName, middleName, lastName, address, }, { merge: true } ); console.log("保存成功"); } catch (err) { console.log(err); } }; return ( <div> {isLoading ? ( <li style={{ listStyle: "none" }}> <CardHeader title="Update Profile" /> <form onSubmit={handleSubmit}> {/* 输入框value绑定对应state,实现双向绑定 */} <TextField type="text" value={firstName} variant="outlined" label="First Name" fullWidth onChange={(e) => setFirstName(e.target.value)} /> <TextField type="text" value={middleName} variant="outlined" label="Middle Name" fullWidth onChange={(e) => setMiddleName(e.target.value)} /> <TextField type="text" value={lastName} variant="outlined" label="Last Name" fullWidth onChange={(e) => setLastName(e.target.value)} /> <TextField type="text" value={address} variant="outlined" label="Address" fullWidth onChange={(e) => setAddress(e.target.value)} /> <Button type="submit">提交</Button> </form> </li> ) : ( <h1>Loading...</h1> )} </div> ); }; export default Edit;
实现说明
- 拉取到用户数据后直接同步给所有表单state作为初始值,即使用户未修改对应字段,state中也保存了原始的正确值,提交时不会出现空值覆盖原有数据的问题
- 输入框和对应state做双向绑定,修改输入内容会实时同步到state
- 提交时的
set操作保留merge: true配置,作为双重保险,避免遗漏字段时覆盖数据库中的已有数据 - 组件名修正为大写开头,符合React组件命名规范
内容的提问来源于stack exchange,提问作者JS3
相关产品推荐
相关产品推荐

