You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:27:01