如何将Google Places Autocomplete自定义组件值同步到Formik对应字段值
解决方案
Formik 向自定义组件注入的 form 对象中内置了 setFieldValue 方法,可用来主动更新指定字段的存储值,配合 react-google-places-autocomplete 组件的回调参数即可完成双向同步。
首先修正原代码的两处小问题:
- Formik 的
initialValues需传入标准对象,写法调整为initialValues={{location: ""}} - 本地
address状态初始化优先取 Formik 注入的field.value,保证表单回填等场景的默认值正确
完整实现代码
import PlacesAutocomplete , { geocodeByAddress, geocodeByPlaceId } from "react-google-places-autocomplete"; import React from "react"; export const PlacesAutoComplete = ({ field: { name, value, onChange, onBlur }, // Formik 注入的字段基础属性 form: { touched, errors, setFieldValue, setFieldTouched, setFieldError }, // Formik 表单操作方法 classes, label, ...props }: any) => { // 本地状态管理输入框显示内容,初始化取Formik存储的字段值 const [address, setAddress] = React.useState(value || ""); const error = errors[name]; // 输入内容变化时触发,同步本地显示+可选实时同步到Formik const handleChange = (inputValue: string) => { setAddress(inputValue); // 若需要实时同步输入内容到Formik,取消下面一行的注释 // setFieldValue(name, inputValue); }; // 选中下拉推荐地址时触发,正式同步到Formik const handleSelect = async (selectedSuggestion: any) => { const selectedAddress = selectedSuggestion.description; setAddress(selectedAddress); // 同步地址文本到Formik对应字段 setFieldValue(name, selectedAddress); // 标记字段已触碰,触发表单校验规则 setFieldTouched(name, true); // 若需要同步获取选中地址的经纬度,可保留下面的逻辑 try { const geoResults = await geocodeByAddress(selectedAddress); const latLng = geoResults[0].geometry.location; // 如需存储经纬度到Formik其他字段,可按下方写法更新 // setFieldValue('locationLat', latLng.lat()); // setFieldValue('locationLng', latLng.lng()); } catch (err) { setFieldError(name, "地址解析失败,请重新选择"); } }; const handleError = () => { setFieldError(name, "地址服务加载失败,请重试"); }; return ( <PlacesAutocomplete value={address} onChange={handleChange} onSelect={handleSelect} onError={handleError} name={name} placeholder={props.placeholder} id={name} {...props} apiKey="Api key here" > {({ getInputProps, suggestions, getSuggestionItemProps, loading }: any) => ( <div> <input {...getInputProps({ placeholder: "Search Places ...", className: "location-search-input form-control", onBlur: onBlur // 绑定Formik的失焦事件,适配校验逻辑 })} /> <div className="autocomplete-dropdown-container"> {loading && <div>Loading...</div>} {suggestions.map((suggestion: any) => { const className = suggestion.active ? "suggestion-item--active" : "suggestion-item"; const style = suggestion.active ? { backgroundColor: "#fafafa", cursor: "pointer" } : { backgroundColor: "#ffffff", cursor: "pointer" }; return ( <div {...getSuggestionItemProps(suggestion, { className, style })} key={suggestion.place_id} > <span>{suggestion.description}</span> </div> ); })} </div> </div> )} </PlacesAutocomplete> ); };
如果你不需要实时同步输入过程中的内容到Formik,只需要用户选中地址后再同步,保留当前handleChange的写法即可;如果需要实时同步,取消handleChange里setFieldValue那行的注释即可。
内容的提问来源于stack exchange,提问作者Onem23
相关产品推荐
相关产品推荐

