0

I'm having trouble showing markers on my app.

I am trying to show markers using @react-google-maps/api for each property that a user owns. The map is rendering but markers are not appearing on the map for some reason.

When I console.log(markers) in Map component, it prints values from the markers array correctly.

When I add empty space or any change to the Map component and saves it, the markers show on the map so code itself works but I think it's to do with the timing of the rendering/ the Map receiving the markers list from PropertyPage component. Navigating to other pages also won't fix it. I tried creating state for markers, using useEffect in PropertyPage (causes infinite re-rendering) and useEffect in Map component and map doesn't render at all.

Below are my codes for the PropertyPage and the Map components. If you could spot any issue, I would very much appreciate it! Thank you in advance!!

/// PropertyPage

import React from 'react'
import PropertyCard from './PropertyCard'
import RingLoader from 'react-spinners/RingLoader';
import Map from './Map';
import { Grid, Button, Image } from 'semantic-ui-react'
import { Link } from 'react-router-dom';
import { useLoadScript } from '@react-google-maps/api'
import { getGeocode, getLatLng } from 'use-places-autocomplete';
import { useGetPropertiesQuery } from '../../app/services/propertiesAPI'

const libraries = ['places']

const PropertyPage = () => {
    const { data: properties = [], isLoading, isError, error, isSuccess } = useGetPropertiesQuery()
    const { isLoaded } = useLoadScript({
        googleMapsApiKey: process.env.REACT_APP_GOOGLEMAPS_KEY,
        libraries,
    });
    let markers = [];
    
    if (!isLoaded) {
        return <div>Map is loading...</div>
    }

    let content

    const generateLatLng = async (address) => {
        try {
            const results = await getGeocode({ address });
            if (results.length === 0) {
             return;
            } else {
                const { lat, lng } = await getLatLng(results[0]);
                if (lat && lng) {
                    markers.push({ lat, lng });
                }
            }
        } catch (error) {
            console.error('Error while generating lat and lng:', error);
        }
    };

    if (isLoading) {
        content = <h1>Loading...</h1>
    } else if (isError) {
        content = <div>{error.toString()}</div>
    } 

    if (isSuccess && properties.length > 0) {
            content = properties.map((property) => <PropertyCard key={property.id} property={property}/>)
            properties.map(property => generateLatLng(property.address))
    }
    

    const noPropertiesYetMessage = (
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            <h1>You have no properties yet.</h1>
            <Button as={Link} to='/properties/add-new'>
                Add More
            </Button>
        <br></br>
        <div style={{ width: '50rem', height: '30rem', position: 'relative', overflow: 'hidden' }}>
            <Image fluid style={{ width: '100%', height: '100%', objectFit: 'cover' }} src='https://www.bhg.com/thmb/TXKtfIyA_UUCOWtMsLXetN5Wvb8=/1493x0/filters:no_upscale():strip_icc()/gray-exterior-white-trim-path-09767f9e-83bad323e9d2473b90e69add9165c12f.jpg' alt='building entrance'/>
        </div>
        </div>
    )

    return (
        <div>
            <RingLoader color={'#F5A623'} loading={isLoading} />
            <div className='ui container hidden divider'>
                { properties && properties.length > 0 ? 
                <Grid Columns={3}>
                    <Grid.Column width={2}>
                    <Button as={Link} to='/properties/add-new' style={{ marginTop: '10px' }}>
                        Add More
                    </Button>
                    <Image src='https://wdy.h-cdn.co/assets/16/05/480x480/square-1454612525-baby-pandas.jpg' size='tiny' circular style={{ marginTop: '10px' }}/>
                    </Grid.Column>
                    { content }
                </Grid> : (noPropertiesYetMessage)}
                <Grid.Row style={{width: '100vw', height: '100vh', paddingTop: '15px'}}>
                    <Map markers={markers}/>
                </Grid.Row>
            </div>
        </div>

    )
}

export default PropertyPage

/// Map component

import { GoogleMap, Marker } from '@react-google-maps/api';

const Map = ({ markers }) => {
    return (
        <GoogleMap zoom={10} center={{lat: 47.6062, lng: -122.3321}} mapContainerStyle={{ width: '80%', height: '80%' }}>
            {markers.map(marker => (
            <Marker key={marker.lat + marker.lng} position={marker}/>)
            )}
        </GoogleMap>

    );

};


export default Map

1 Answers1

0

I was able to figure this out. Instead of converting address to latitude and longitude every time the page renders, I convert when the property instance is created/updated and save the latitude and longitude values in properties tables. That way, when the property page is rendered, I just need to get those values from the properties data like other variables and it solved the issue of non-rendering when using variable/ infinite re-rendering when using state. I hope this helps!!