React+Firebase Firestore场景下如何更新动态渲染列表的单条记录age字段
问题根源
你当前的写法存在两个核心问题:
- 全局只维护了一个
age状态,所有用户的修改输入都会复用这同一个状态,自然会出现改一个全量同步的问题 - 提交更新时
docID是硬编码的固定值,没有和你要修改的对应用户文档做绑定 - 额外注意:
Button组件的触发事件是onClick不是onChange,你原有代码这里写错会导致提交逻辑不触发
解决方案1:修改控件嵌入每个用户项(独立维护状态)
把年龄输入和提交按钮放到每个用户的渲染条目内,每个条目独立维护自己的输入状态,直接绑定当前遍历到的用户doc.id:
data.map( (doc) => { // 每个用户项单独维护自己的年龄输入状态,默认值取现有年龄 const [curAge, setCurAge] = useState(doc.age); // 提交修改时直接用当前项的doc.id生成文档引用 const handleUpdateAge = async () => { const userRef = doc(db, "user", doc.id); await updateDoc(userRef, { age: curAge }); } return ( <div key={doc.id}> <div>姓名:{doc.name}</div> <div>当前年龄:{doc.age}</div> <div> <TextField value={curAge} onChange={e => setCurAge(e.target.value)} placeholder="输入新年龄" /> <Button onClick={handleUpdateAge}> 提交年龄修改 </Button> </div> </div> ) })
解决方案2:仅保留一个全局修改框(加选中用户状态)
如果不想每个用户项都放输入控件,可以新增一个「选中待修改用户ID」的状态,点击对应用户的修改按钮后把ID赋值给状态,提交时直接用这个ID即可:
// 新增选中待修改用户的ID状态 const [selectedUserId, setSelectedUserId] = useState(null); const [age, setAge] = useState(1); const handleSubmitAge = async () => { // 未选中用户时不执行提交 if (!selectedUserId) return; const ageRef = doc(db, "user", selectedUserId) await updateDoc(ageRef, { age : age }); } // 渲染逻辑 return ( <div> {/* 遍历用户列表 */} {data.map( (doc) => { return ( <div key={doc.id}> <div>姓名:{doc.name}</div> <div>年龄:{doc.age}</div> <Button onClick={() => { // 选中用户时同时把ID和现有年龄填充到状态 setSelectedUserId(doc.id); setAge(doc.age); }}> 修改该用户年龄 </Button> </div> ) })} {/* 全局修改区域 */} <div> <TextField value={age} onChange={ e => setAge(e.target.value)} /> <Button onClick={handleSubmitAge}> 提交年龄 </Button> </div> </div> )
额外注意
React遍历渲染列表项时必须给每个根元素加key属性,直接用doc.id作为key即可,符合React的渲染要求。
内容的提问来源于stack exchange,提问作者Vincentius Heri
相关产品推荐
相关产品推荐

