Material UI Autocomplete无法获取异步函数返回的邮政编码问题
问题原因分析
你这段代码的核心问题出在异步操作的执行时机和React渲染机制不匹配:
getPostCode是异步函数,当renderOption返回<li>时,异步请求还没完成,zipCode还是初始的空字符串,所以页面上看不到结果。- 直接给局部变量
zipCode赋值不会触发组件重新渲染,就算后续异步请求拿到了邮政编码,页面也不会自动更新显示。
解决方案
方案一:提前预加载所有选项的邮政编码(推荐)
在组件拿到data后,批量获取每个地点的邮政编码并存在选项对象里,避免渲染时频繁发起异步请求:
const Places = () => { const [optionsWithZip, setOptionsWithZip] = useState([]); useEffect(() => { const fetchZipCodes = async () => { const updatedOptions = await Promise.all( data.map(async (option) => { try { const results = await getGeocode({ placeId: option.place_id }); const zipCode = getZipCode(results[0], true); return { ...option, zipCode }; } catch (error) { console.log(error); return { ...option, zipCode: '' }; } }) ); setOptionsWithZip(updatedOptions); }; if (data.length > 0) { fetchZipCodes(); } }, [data]); return ( <Autocomplete options={optionsWithZip} getOptionLabel={(option) => typeof option === 'string' ? option : option.description} filterOptions={(x) => x} renderInput={(params) => <TextField {...params} label='Location' />} onInputChange={(event, newValue) => setValue(newValue)} renderOption={(props, option) => ( <li {...props} > {`${option.terms[0].value}, ${option.terms[1]?.value}, ${option.zipCode}`} </li> )} /> ); }
方案二:为单个选项单独处理异步请求
如果不想批量预加载,可以把每个选项的渲染拆成独立组件,用状态管理单个选项的邮政编码:
const Places = () => { const [zipCodesCache, setZipCodesCache] = useState({}); const OptionItem = ({ props, option }) => { const [zipCode, setZipCode] = useState(zipCodesCache[option.place_id] || ''); useEffect(() => { if (!zipCode) { const fetchZip = async () => { try { const results = await getGeocode({ placeId: option.place_id }); const code = getZipCode(results[0], true); setZipCode(code); setZipCodesCache(prev => ({ ...prev, [option.place_id]: code })); } catch (error) { console.log(error); } }; fetchZip(); } }, [option.place_id, zipCode]); return ( <li {...props} > {`${option.terms[0].value}, ${option.terms[1]?.value}, ${zipCode}`} </li> ); }; return ( <Autocomplete options={data} getOptionLabel={(option) => typeof option === 'string' ? option : option.description} filterOptions={(x) => x} renderInput={(params) => <TextField {...params} label='Location' />} onInputChange={(event, newValue) => setValue(newValue)} renderOption={(props, option) => ( <OptionItem props={props} option={option} /> )} /> ); }
内容的提问来源于stack exchange,提问作者Clippit
相关产品推荐
相关产品推荐

