React中子组件状态变更后未更新数据的问题排查
问题:切换选中用户后表单数据不更新
我有一个用户列表,期望点击任意用户时,在页面右侧的表单组件中展示该用户的数据;未选中用户时,右侧只显示文本和「添加新用户」按钮,点击按钮后渲染空表单用于新增用户。但现在的问题是,第一次点击用户能正常显示数据,后续切换其他用户时,表单数据完全没变化。
主页面代码
const index = (props) => { const [selectedUser, setSelectedUser] = useState(null); const [state, setState] = useState("Index"); const onChange = (item) => { setState("Edit"); setSelectedUser(item); }; const onClick = (e, item) => { if (e.type === "click" && e.clientX !== 0 && e.clientY !== 0) { onChange(item); } else { console.log('prevented "onClick" on keypress'); } }; const renderComponent = () => { switch (state) { case "Index": return ( <> <div className="btn" onClick={(e) => setState("Edit")}> + New Staff </div> <img src="/storage/illustrations/collaboration.svg" /> </> ); case "Edit": return ( <div> <StaffForm profile={selectedUser} /> </div> ); } }; return ( <> <div> <div> <h1>Staff</h1> </div> <div> <div> {profiles.map((item, index) => { return ( <div key={index} onClick={(e) => onClick(e, item)}> <input type="radio" name="staff" checked={state === item} onChange={(e) => onChange(item)} /> <span>{item.user.name}</span> </div> ); })} </div> <div>{renderComponent()}</div> </div> </div> </> ); };
StaffForm组件代码
const StaffForm = ({ profile }) => { const { data, setData, post, processing, errors, reset } = useForm({ email: profile ? profile.user.email : "", name: profile ? profile.user.name : "", phone_number: profile ? profile.user.phone_number : "", avatar: profile ? profile.user.avatar : "", }); const [file, setFile] = useState(data.avatar); const handleImageUpload = (e) => { setFile(URL.createObjectURL(e.target.files[0])); setData("avatar", e.target.files[0]); }; const onHandleChange = (event) => { setData( event.target.name, event.target.type === "checkbox" ? event.target.checked : event.target.value ); }; return ( <div> <ImageUpload name={data.name} file={file} handleImageUpload={handleImageUpload} /> <TextInput type="text" name="name" value={data.name} autoComplete="name" isFocused={true} onChange={onHandleChange} placeholder={t("Name")} required /> <TextInput type="text" name="phone_number" value={data.phone_number} autoComplete="phone_number" placeholder={t("Phone Number")} onChange={onHandleChange} required /> <TextInput type="email" name="email" value={data.email} autoComplete="email" onChange={onHandleChange} placeholder={t("Email")} required /> </div> ); };
解决方案
1. 修复表单数据不更新问题
useForm的初始值仅在组件首次挂载时设置,后续profile props变化不会自动更新表单。需要添加useEffect监听profile变化,手动重置表单数据:
const StaffForm = ({ profile }) => { const { data, setData, post, processing, errors, reset } = useForm({ email: profile ? profile.user.email : "", name: profile ? profile.user.name : "", phone_number: profile ? profile.user.phone_number : "", avatar: profile ? profile.user.avatar : "", }); const [file, setFile] = useState(data.avatar); // 监听profile变化,同步更新表单和头像文件 useEffect(() => { if (profile) { const newData = { email: profile.user.email, name: profile.user.name, phone_number: profile.user.phone_number, avatar: profile.user.avatar, }; reset(newData); setFile(newData.avatar); } else { reset({ email: "", name: "", phone_number: "", avatar: "", }); setFile(""); } }, [profile, reset]); // 其余代码保持不变 };
2. 修复单选框选中状态错误
主页面中单选框的checked判断逻辑错误,state是字符串类型,不可能和用户对象item相等,应该用selectedUser来判断:
<input type="radio" name="staff" checked={selectedUser === item} // 修改此处 onChange={(e) => onChange(item)} />
3. 简化冗余的点击事件判断
主页面中onClick函数里的clientX/clientY判断无意义,且可能导致正常点击失效,直接简化:
const onClick = (e, item) => { onChange(item); };
甚至可以去掉外层div的onClick,仅保留单选框的onChange事件,更符合表单交互逻辑。
内容的提问来源于stack exchange,提问作者Abdelhk
相关产品推荐
相关产品推荐

