I have a Map
component where I created a function to get the user's current location. I have imported this map component into a larger RetailLocations
component. I want to assign the handleClick()
function created in the Map
component to a button in the RetailLocations
component. The relevant code:
Map Component code:
const [center, setCenter] = useState({ lat: 0, lng: 0 });
const location = useGeoLocation();
const mapRef = useRef();
const ZOOM_LEVEL = 20;
const handleClick = (e) => {
if (location.loaded) {
mapRef.current.leafletElement.flyTo(
[location.coordinates.lat, location.coordinates.lng],
ZOOM_LEVEL,
{ animate: true }
);
}
};
return <>
<MapContainer
center={center}
zoom={ZOOM_LEVEL}
ref={mapRef}
scrollWheelZoom={false}
className={style.mapContainer}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
{location.loaded && (
<Marker position={[ location.coordinates.lat, location.coordinates.lng ]}></Marker>
)}
</MapContainer>
</>;
};
export default Map;
This is the RetailLocations component's relevant code:
import Map from './Map';
....
<button
className={style.locationBtn}
onClick={handleClick}
>My Location</button>
....
Is there something else I'm missing?
CodePudding user response:
you should read this. from pluralsight: Components are an integral part of React. Each React application consists of several components, and each component may require user interaction that triggers various actions. To achieve user interactivity, we can call functions and methods to accomplish specific operations in React. We pass data from parent to child or child to parent components using these actions. https://www.pluralsight.com/guides/how-to-reference-a-function-in-another-component
CodePudding user response:
Use forwardRef and useImperativeHandle hooks to access method inside a functional component.
Map component:
import { forwardRef, useImperativeHandle } from 'react'
const Map = forwardRef((props, ref) => {
...
const handleClick = (e) => {
if (location.loaded) {
mapRef.current.leafletElement.flyTo(
[location.coordinates.lat, location.coordinates.lng],
ZOOM_LEVEL,
{ animate: true }
);
}
};
useImperativeHandle(
ref,
() => ({ handleClick }),
[handleClick]
);
return <>
<MapContainer
center={center}
zoom={ZOOM_LEVEL}
ref={mapRef}
scrollWheelZoom={false}
className={style.mapContainer}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
{location.loaded && (
<Marker position={[ location.coordinates.lat, location.coordinates.lng ]}></Marker>
)}
</MapContainer>
</>;
})
RetailLocations component:
import Map from './Map';
import { useRef } from 'react';
....
const RetailLocations = () => {
const ref = useRef()
return <>
<Map ref={ref} />
<button
className={style.locationBtn}
onClick={(e) => ref.current.handleClick(e)}>
My Location
</button>
</>
}
....