单个React Recoil atom存储多个表单值时互相覆盖如何解决
问题根因
你当前的代码存在两个核心问题:
registerAtom的默认值使用了数组,没有按字段区分存储邮箱、手机号两个独立值- 两次调用
useSetRecoilState拿到的都是同一个atom的全局修改方法,每次赋值都是直接覆盖整个atom的完整值,自然会出现两个输入互相覆盖的情况
修复方案
首先将atom的默认值修改为对象,按字段区分存储不同的表单值,修改时通过旧值展开的方式保留其他字段的内容,不要直接覆盖整个atom。
完整修改后的代码如下:
import { atom, useSetRecoilState, useRecoilValue } from 'recoil'; // atom默认值改为对象,区分存储不同字段 const registerAtom = atom({ key: 'register', default: { email: '', phone: '' }, }); function Registration() { // 只需要获取一次atom的值和修改方法即可 const registerInfo = useRecoilValue(registerAtom); const setRegisterInfo = useSetRecoilState(registerAtom); return ( <> <form> <input name="email" type="text" className="form-control" value={registerInfo.email} // 赋值时先展开旧值保留其他字段,仅更新当前字段 onChange={e => setRegisterInfo(prev => ({ ...prev, email: e.target.value }))} placeholder="Email Address" /> <input name="phone" type="text" className="form-control" value={registerInfo.phone} onChange={e => setRegisterInfo(prev => ({ ...prev, phone: e.target.value }))} placeholder="Phone Number" /> </form> </> ) }
优化建议
如果表单字段较多,可以封装通用的更新方法,减少重复代码:
function Registration() { const registerInfo = useRecoilValue(registerAtom); const setRegisterInfo = useSetRecoilState(registerAtom); // 通用更新方法,只要input的name属性和atom内的字段名对应即可自动更新 const handleInputChange = (e) => { const { name, value } = e.target; setRegisterInfo(prev => ({ ...prev, [name]: value })) } return ( <> <form> <input name="email" type="text" className="form-control" value={registerInfo.email} onChange={handleInputChange} placeholder="Email Address" /> <input name="phone" type="text" className="form-control" value={registerInfo.phone} onChange={handleInputChange} placeholder="Phone Number" /> </form> </> ) }
内容的提问来源于stack exchange,提问作者BigJobbies
相关产品推荐
相关产品推荐

