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

NextJS组件向页面传递数据的最佳实践:地点自动完成组件回传经纬度

实现可复用地点自动完成组件并回传地理编码的最佳实践

对于需要复用且需回传数据的组件,受控组件+回调函数是最符合React开发直觉的最佳实践。核心思路是让父组件通过props传入回调函数,子组件在完成地点选择并获取到地理编码后,调用该回调将数据传递给父组件;同时支持父组件控制输入值,保证组件的灵活性和复用性。

修改后的地点自动完成组件(PlacesAutocomplete.jsx)

import usePlacesAutocomplete, {
  getGeocode,
  getLatLng,
} from "use-places-autocomplete";
import useOnclickOutside from "react-cool-onclickoutside";

// 接收父组件传入的props:onSelect(回调)、value(受控值)、onChange(值变化回调)、placeholder
const PlacesAutocomplete = ({ onSelect, value, onChange, placeholder = "输入地点" }) => {
  const {
    ready,
    suggestions: { status, data },
    setValue: setInternalValue,
    clearSuggestions,
  } = usePlacesAutocomplete({
    callbackName: "YOUR_CALLBACK_NAME",
    requestOptions: {
      /* 定义搜索范围 */
    },
    debounce: 300,
  });
  const ref = useOnclickOutside(() => {
    clearSuggestions();
  });

  // 处理输入变化,同步给父组件
  const handleInput = (e) => {
    const inputValue = e.target.value;
    setInternalValue(inputValue);
    onChange?.(inputValue);
  };

  const handleSelect =
    ({ description }) =>
    async () => {
      setInternalValue(description, false);
      clearSuggestions();
      onChange?.(description);

      // 获取经纬度并回传给父组件
      try {
        const results = await getGeocode({ address: description });
        const { lat, lng } = getLatLng(results[0]);
        // 调用父组件传入的回调,传递地址和经纬度
        onSelect?.({ address: description, lat, lng });
      } catch (err) {
        console.error("获取地理编码失败:", err);
      }
    };

  const renderSuggestions = () =>
    data.map((suggestion) => {
      const {
        place_id,
        structured_formatting: { main_text, secondary_text },
      } = suggestion;

      return (
        <li key={place_id} onClick={handleSelect(suggestion)}>
          <strong>{main_text}</strong> <small>{secondary_text}</small>
        </li>
      );
    });

  return (
    <div ref={ref}>
      <input
        value={value || ""}
        onChange={handleInput}
        disabled={!ready}
        placeholder={placeholder}
      />
      {status === "OK" && <ul>{renderSuggestions()}</ul>}
    </div>
  );
};

export default PlacesAutocomplete;

使用组件的页面(index.jsx)

import { useState } from "react";
import PlacesAutocomplete from "@/components/PlacesAutocomplete";

export default function Example() {
  // 分别管理出发地和目的地的地址、经纬度
  const [origin, setOrigin] = useState({ address: "", lat: null, lng: null });
  const [destination, setDestination] = useState({ address: "", lat: null, lng: null });

  return (
    <div className="bg-white">
      <div>
        <h3>出发地</h3>
        <PlacesAutocomplete
          placeholder="请输入出发地"
          value={origin.address}
          onChange={(address) => setOrigin(prev => ({ ...prev, address }))}
          onSelect={(data) => setOrigin(data)}
        />
        {origin.lat && <p>出发地坐标:{origin.lat}, {origin.lng}</p>}
      </div>
      <div style={{ marginTop: "20px" }}>
        <h3>目的地</h3>
        <PlacesAutocomplete
          placeholder="请输入目的地"
          value={destination.address}
          onChange={(address) => setDestination(prev => ({ ...prev, address }))}
          onSelect={(data) => setDestination(data)}
        />
        {destination.lat && <p>目的地坐标:{destination.lat}, {destination.lng}</p>}
      </div>
    </div>
  );
}

方案优势

  • 高复用性:组件封装了自动完成的核心逻辑,父组件只需传入不同的回调和配置,即可实现多个实例的差异化使用,无需重复初始化输入框逻辑。
  • 符合单向数据流:数据由父组件管理,子组件仅负责UI渲染和触发回调,保证了React应用的数据流向清晰,便于维护。
  • 灵活性强:支持受控模式(父组件控制输入值)和非受控模式(组件内部管理值),可根据需求调整;同时支持自定义占位符等配置。

内容的提问来源于stack exchange,提问作者BernardL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:55:35