I'm using @googlemaps/react-wrapper to make a map component in my react application using the example from googlemaps, and adding an event on drag marker to refresh coordinates, this works fine now. but i need to call the map component outside to refresh a input value with the coordiantes. The error i get it is:
Binding element 'childToParent' implicitly has an 'any' type.* Please could help me to understand how i could send the values to paren using typescript Greetings In parent i have this
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>
);
My Location map component is like this
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;
CodePudding user response:
It is warning you because you have not passed the correct function. This should fix the problem:
const [coordinate, setCoordinate] = useState("");