React useState定义的房源对象中如何正确更新嵌套location属性
问题1:本地状态初始化逻辑存在时序问题
你在useEffect中先触发异步拉取房源的getListing方法,同步就执行了setEditListing(listing),此时异步请求尚未返回,redux中取出的listing还是初始空值,当前表单能填充默认值只是偶现的时序巧合,后续极大概率出现默认值丢失问题。
修正后的初始化代码:
const listing = useSelector((state) => state.listings.listing); const [editListing, setEditListing] = React.useState({}); // 组件挂载时触发拉取房源数据 React.useEffect(() => { getListing(listingId)(dispatch); }, [listingId, dispatch]); // 监听redux中房源数据变化,拿到有效数据后再同步到本地编辑状态 React.useEffect(() => { if (Object.keys(listing || {}).length) { setEditListing(listing); } }, [listing]);
问题2:嵌套对象location的更新逻辑错误
你更新location时直接将整个location对象替换为仅包含当前修改字段的新对象,自然会清空location下其他未修改的字段,同时你还误将字段值用数组包裹,导致值类型不符合预期。
修正后的表单处理逻辑:
const handleChange = (e) => { const { name, value } = e.target; const locationFields = ['country', 'city', 'state']; setEditListing((prevListing) => ({ ...prevListing, // 判断当前修改的是否为location下的字段 ...(locationFields.includes(name) ? { location: { ...prevListing.location, // 保留原有location下的所有字段 [name]: value // 覆盖当前修改的字段 } } : { [name]: value } ) })); };
如果你的location字段的输入框name属性用了location.city这类带前缀的命名,额外加个字段名拆分逻辑即可,上面的代码适配你当前name直接为city/country/state的场景。
内容的提问来源于stack exchange,提问作者Stinny
相关产品推荐
相关产品推荐

