【问题标题】:pass coordinates from googlemaps react child to parent in functional component typescript在功能组件打字稿中,从 googlemaps 将坐标传递给父级
【发布时间】:2022-10-06 14:48:14
【问题描述】:

我正在使用@googlemaps/react-wrapper 使用googlemaps 中的示例在我的react 应用程序中制作地图组件,并在拖动标记上添加一个事件以刷新坐标,现在可以正常工作。但我需要调用外面的地图组件来用坐标刷新输入值。 我得到的错误是:

绑定元素 \'childToParent\' 隐式具有 \'any\' 类型。* 请帮助我了解如何使用打字稿将值发送给paren 问候 在父母我有这个

 const [coordinate,SetCoordinate]=useState(\"\");  
return (
        <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
            <Stack spacing={3}>

                <RHFTextField name=\"lat\" label=\"Coord X\" />
                <RHFTextField name=\"lng\" label=\"Coord Y\" />

            </Stack>
            <Stack>
                <br/>
                <LocationMap  childToParent={setCoordinate}/>
            </Stack>
            <Stack>

                <LoadingButton
                    fullWidth
                    size=\"large\"
                    type=\"submit\"
                    variant=\"contained\"
                >
                    Save
                </LoadingButton>
            </Stack>
        </FormProvider>
    );

我的位置图组件是这样的

const render = (status: Status) => {
  return <h1>{status}</h1>;
};
interface MapProps extends google.maps.MapOptions {
  style: { [key: string]: string };
  onClick?: (e: google.maps.MapMouseEvent) => void;
  onIdle?: (map: google.maps.Map) => void;
}
//function to pass value to parent
interface LocationProps {
  childToParent: (arg0: string)=>string;
}
export default function LocationMap({childToParent,...props}){

  const [clicks, setClicks] = useState<google.maps.LatLng[]>([]);
  const [zoom, setZoom] = useState(3); // initial zoom
  const [center, setCenter] = useState<google.maps.LatLngLiteral>({
    lat: 0.0,
    lng: 0.0,
  });
  const [markerLocation, setMarkerLocation] = useState<google.maps.LatLng>();
  const dragend = (e: google.maps.MapMouseEvent) => {
    // avoid directly mutating state
    setMarkerLocation(e.latLng!)
    setClicks([...clicks, e.latLng!]);

  };

  const onClick = (e: google.maps.MapMouseEvent) => {
  };
  const onIdle = (m: google.maps.Map) => {
    //.log(\"onIdle\");
    setZoom(m.getZoom()!);
    setCenter(m.getCenter()!.toJSON());
  };

  const ref = useRef<HTMLDivElement>(null);
  const [map, setMap] = useState<google.maps.Map>();
  useEffect(() => {
    if (ref.current && !map) {
      setMap(new window.google.maps.Map(ref.current, {}));
    }

  }, [ref, map]);

  return (
    <>
      <div style={{ display: \"flex\", height: \"100%\" }}>
        <Wrapper apiKey={apiKey} render={render}>
          <Map
            center={center}
            onClick={onClick}
            onIdle={onIdle}
            zoom={zoom}
            style={{ flexGrow: \"1\", height: \"25em\", width: \"400px\" }}
          >


            <Marker key=\"point\" draggable={true} dragend={dragend} />


          </Map>

        </Wrapper>
      </div>
      <div id=\"coordinate\">
        {clicks.map(function (latLng, i, row) {
          var element = document.getElementById(\"coordenadas\");
          if (element === null) {
            console.error(\"error cleaning coordinates\");
          } else {
            element.innerHTML = \"\";
          }
          return (
          childToParent(latLng.toJSON())
          );
        })
        }
      </div>
    </>
  )
};

interface MapProps extends google.maps.MapOptions {
  onClick?: (e: google.maps.MapMouseEvent) => void;
  onIdle?: (map: google.maps.Map) => void;
}
const Map: React.FC<MapProps> = ({
  onClick,
  onIdle,
  children,
  style,
  ...options
}) => {
  const ref = useRef<HTMLDivElement>(null);
  const [map, setMap] = useState<google.maps.Map>();

  useEffect(() => {
    if (ref.current && !map) {
      setMap(new window.google.maps.Map(ref.current, {}));
    }
  }, [ref, map]);

  // because React does not do deep comparisons, a custom hook is used
  // see discussion in https://github.com/googlemaps/js-samples/issues/946
  useDeepCompareEffectForMaps(() => {
    if (map) {
      map.setOptions(options);
    }
  }, [map, options]);

  useEffect(() => {
    if (map) {
      [\"click\", \"idle\"].forEach((eventName) =>
        google.maps.event.clearListeners(map, eventName)
      );

      if (onClick) {
        map.addListener(\"click\", onClick);
      }

      if (onIdle) {
        map.addListener(\"idle\", () => onIdle(map));
      }
    }
  }, [map, onClick, onIdle]);

  return (
    <>
      <div ref={ref} style={style} />
      {Children.map(children, (child) => {
        if (isValidElement(child)) {
          // set the map prop on the child component
          return cloneElement(child, { map });
        }
      })}
    </>
  );
};
interface MarkerProps extends google.maps.MarkerOptions {
  dragend?: (e: google.maps.MapMouseEvent) => void;
}
const Marker: React.FC<MarkerProps> = ({
  dragend,
  ...options
}) => {
  const [marker, setMarker] = useState<google.maps.Marker>();
  console.log(options);

  useEffect(() => {

    if (!marker) {
      setMarker(new google.maps.Marker({
        position: {
          lat: 0,
          lng: 0,
        },
      }));
    }

    // remove marker from map on unmount
    return () => {

      if (marker) {
        marker.setMap(null);
      }
    };
  }, [marker]);

  useEffect(() => {
    if (marker) {
      marker.setOptions(options);
    }
  }, [marker, options]);

  useEffect(() => {
    if (marker) {
      [\"dragend\"].forEach((eventName) =>
        google.maps.event.clearListeners(marker, eventName)
      );
      marker.setOptions(options);
      if (dragend) {
        //map.addListener(\"click\", onClick);
        marker.addListener(\"dragend\", dragend);

      }
    }
  }, [marker, dragend, options]);

  return null;
};
const deepCompareEqualsForMaps = createCustomEqual(
  (deepEqual) => (a: any, b: any) => {
    if (
      isLatLngLiteral(a) ||
      a instanceof google.maps.LatLng ||
      isLatLngLiteral(b) ||
      b instanceof google.maps.LatLng
    ) {
      return new google.maps.LatLng(a).equals(new google.maps.LatLng(b));
    }

    // TODO extend to other types

    // use fast-equals for other objects
    return deepEqual(a, b);
  }
);

function useDeepCompareMemoize(value: any) {
  const ref = useRef();

  if (!deepCompareEqualsForMaps(value, ref.current)) {
    ref.current = value;
  }

  return ref.current;
}

function useDeepCompareEffectForMaps(
  callback: React.EffectCallback,
  dependencies: any[]
) {
  useEffect(callback, dependencies.map(useDeepCompareMemoize));
}
export default LocationMap;

    标签: reactjs typescript google-maps


    【解决方案1】:

    它警告您,因为您没有通过正确的功能。这应该可以解决问题:

    const [coordinate, setCoordinate] = useState("");
    

    【讨论】:

    • 感谢您的快速回复。我更新了父级中的 const 并像这样传递给位置图: ´´´ <LocationMap childToParent={setCoordinate}/>´´´ 但消息仍然是绑定元素 'childToParent' 隐含具有 'any' 类型
    • 函数区分大小写。在 useState 中,您编写了 SetCoordimate,大写为 S
    【解决方案2】:

    const deepCompareEqualsForMaps = createCustomEqual((deepEqual: any, ref: any) => (a: any, b: any) => { 如果 ( isLatLngLiteral(a) || window.google.maps.LatLng 的实例 || isLatLngLiteral(b) || b instanceof window.google.maps.LatLng ) { 返回新窗口.google.maps.LatLng(a).equals(新窗口.google.maps.LatLng(b)); }

    // TODO extend to other types
    
    // use fast-equals for other objects
    return deepEqual(a, b);
    

    } );

    【讨论】:

      猜你喜欢
      • 2021-02-28
      • 2017-08-04
      • 2022-06-10
      • 2020-06-22
      • 2021-11-20
      • 1970-01-01
      • 2020-02-09
      • 2018-07-31
      • 2021-06-13
      相关资源
      最近更新 更多