Context
I'm trying to use google-map-react
to show local bakery stores.
However, the line console.log(props);
in my child component StoresGoogleMap
prints storeLocations
and stores
as []
. If I use below instead in my StoresGoogleMap
component, the it is working:
{props.storeLocations.map((storeLocation) => (
<Marker
key={storeLocation.unique_store_name}
lat={storeLocation.store_location_latitude}
lng={storeLocation.store_location_longitude}
store={storeLocation}
/>
))}
So I think here the problem is that the child component StoresGoogleMap
is rendered with initial value in parent component SearchStoresPage
, which is []
. But not updated when parent component's state changed.
Any suggestion how to fix this?
Details
I have a parent component defined like this:
const SearchStoresPage = () => {
const [state, setState] = React.useState<StateProperties>(
{stores:[], storeLocations: []}
);
React.useEffect(
() => {
searchStores()
.then(
response => {
const locations : GoogleMapStoreLocation[] = response.map(
(obj:TypeStore) => {
return (
{
store_id: obj['store_id'],
store_name: obj['store_name'],
unique_store_name: obj['unique_store_name'],
store_description: obj['store_description'],
store_website: obj['store_website'],
store_cell_number: obj['store_cell_number'],
store_email: obj['store_email'],
store_location: obj['store_location'],
store_location_latitude: obj['store_location_latitude'],
store_location_longitude: obj['store_location_longitude'],
show: false
}
)
}
);
setState({stores: response, storeLocations: locations});
}
)
.catch(error => console.log(error));
},
[]
);
return (
<div className="flex flex-row">
<StoreList storeList = {state.stores}/>
<StoresGoogleMap storeLocations = {state.storeLocations} stores = {state.stores} defaultCenter={[40.7831, -73.9712]}/>
</div>
);
};
And I have a child component StoresGoogleMap
defined like this:
const StoresGoogleMap = (props: StoresGoogleMapProps) => {
const [storeLocations, setStoreLocations] = React.useState<GoogleMapStoreLocation[]>(props.storeLocations);
React.useEffect(
() => {
console.log(props);
setStoreLocations(props.storeLocations);
},
[]
);
const onMarkerClick = (unique_store_name: string) => {
...
};
return (
<div id="map" style={{ height: '100vh', width: '100%' }}>
<GoogleMap
defaultZoom={12}
defaultCenter={props.defaultCenter}
bootstrapURLKeys={{ key: process.env.REACT_APP_GOOGLE_MAP_API_KEY }}
onChildClick={onMarkerClick}
>
{storeLocations.map((storeLocation) => (
<Marker
key={storeLocation.unique_store_name}
lat={storeLocation.store_location_latitude}
lng={storeLocation.store_location_longitude}
store={storeLocation}
/>
))}
</GoogleMap>
</div>
);
};
CodePudding user response:
So I think here the problem is that the child component StoresGoogleMap is rendered with initial value in parent component SearchStoresPage, which is []. But not updated when parent component's state changed. Any suggestion how to fix this?
A way to fix this is to fire useEffect
in your child component when data in parent component changes --> By adding props.storeLocations
as a dependency in StoresGoogleMap
useEffect()
CodePudding user response:
Because you are passing empty array []
in your child component's useEffect so it runs only 1st time when it renders.
Now let's say your data was fetched hence child component will be re-rendered but your useEffect will not run again since you passed an empty array in the dependency.
So you can safely use props.storeLocations.map
or remove []
from useEffect that will cause the useEffect run on every single render or if you really want to use state variable add props.storeLocations
to your child useEffect dependency