Search code examples
javascriptreactjslazy-loading

Converting React.lazy object to JSX element


I have a component called GoogleMap.js. I want to import it if user scrolls, so I made it lazy import but it doesn't return JSX. Instead it returns React.lazy object. So I cannot render it in JSX. How can I render it with in JSX. Also, if I use it like that, does it import react google map even though use doesn't scroll the page.

import React from 'react'
import GoogleMapReact from 'google-map-react'
import styled from 'styled-components'

const GoogleMapWrapper = styled.div`
    height: 40vh; 
    width: 60vw;
    margin: 50px auto;
    border: 1px solid red;
`

function GoogleMap() {

    return (
        <GoogleMapWrapper>
            <GoogleMapReact
                bootstrapURLKeys={{ key: 'AIzaSyAER*******************zs0' }}
                defaultCenter={{
                    lat: -3.745,
                    lng: -38.523
                }}
                defaultZoom={3}
            >
                <div
                    lat={59.955413}
                    lng={30.337844}
                    text="My Marker"
                />
            </GoogleMapReact>
        </GoogleMapWrapper>
    )
}

export default GoogleMap
 useEffect(() => {
        if (isImported) {
            window.removeEventListener('scroll', scrollDetector)
            const GoogleMap = React.lazy(() => import('../../components/DynamicLandingPages/GoogleMap'))
            console.log("type:", typeof GoogleMap)
            console.log("OBJ:", GoogleMap)
            setGoogleMapComponent(GoogleMap)
        }
    }, [isImported])

Note: googleMapComponent is a react state. Set is its setter function.

<Suspense fallback={<GoogleMapWrapper />}>
    <googleMapComponent />
</Suspense>

Here is what it returns:

{$$typeof: Symbol(react.lazy), _status: -1, _result: null, _ctor: ƒ, …}

Solution

  • You are abusing React state. You shouldn't keep components as state ! Also, this <googleMapComponent /> is wrong. More details in docs.

    Finally, is there any reason for using React.lazy in useEffect ?

    It should be used something like this:

    // some MyComponent.js file
    
    // ... normal imports ...
    
    const GoogleMap = React.lazy(() => import('../../components/DynamicLandingPages/GoogleMap'));
    
    function MyComponent() {
      return (
        <div>
          <Suspense fallback={<div>Loading...</div>}>
            <GoogleMap />
          </Suspense>
        </div>
      );
    }
    

    If you need something to be rendered when you scroll to certain position, than you might want add some state - something like isElementInViewport, you need a piece of JS to actually figure that out and set that state to true when it happens and then you can do stuff like:

    {isElementInViewport  
    && (Suspense fallback={<div>Loading...</div>}>
        <GoogleMap />
    </Suspense>)}