2

I have an a component that crashes my app when a device goes offline. This is because it uses Google Maps, which requires an internet connection. I would like to catch this failed Google Maps import and show an error message (as right now my app just shows a blank screen). Here's an example:

import { GoogleMap, withGoogleMap, Marker, Polyline, Polygon } from 'react-google-maps'

interface IProps {
    center: google.maps.LatLng
    points: google.maps.LatLng[]
    location: google.maps.LatLng | null
    target: google.maps.LatLng[] | null
}

const MARKER_LABEL: google.maps.MarkerLabel = {
    color: '#fff',
    fontSize: '14px',
    text: 'Sample Marker Text'
}

// some more consts....

const MapComponent = (props: IProps): JSX.Element => (
    <GoogleMap center={props.center} defaultMapTypeId={google.maps.MapTypeId.HYBRID} zoom={22} options={OPTIONS}>
        <ZoomLayer maxZoom={22} />
        <Polyline options={POLYLINE_OPTIONS} path={props.points} />
        {props.target !== null && props.location !== null ? <Polyline options={POLYLINE_TO_CENTER_OPTIONS} path={[props.location, averagePoint(props.target)]} /> : null}
        <Marker label={MARKER_LABEL} position={props.location || props.center} icon={MARKER_ICON} />
        {props.target !== null && props.target.length === 1 ? <Marker position={props.center} icon={MARKER_TARGET_ICON} /> : null}
        {props.target !== null && props.target.length > 1 ? <Polygon path={props.target} options={POLYGON_TARGET_OPTIONS} /> : null}
    </GoogleMap>
)

const Map = compose<IProps, IProps>(
    withProps({
        loadingElement: <div className='loading' />,
        containerElement: <div className='map' />,
        mapElement: <div />
    }),
    withGoogleMap
)(MapComponent)

export default Map

The error message is Map.tsx:13 Uncaught ReferenceError: google is not defined when I run this offline. I'm not sure what the "React" way of handling this is, and I've been searching things like "React catch failed import" but haven't found anything. I think ideally I'd want something like

try {
    console.log("FIND GOOGLE: ", google)
} catch (error) {
    export default error
}

Update #1

I tried catching after I import my potentially-breaking component:

try {
    return (
        <section id='path' className='loading-parent'>
            <Map center={center}
                points={points.map(point => new google.maps.LatLng(point.lat, point.lng))}
                location={location}
                target={target} />
            {content}
            {loading ? <div className='loading' /> : null}
        </section>
    )
} catch (e) {
    return(
        <div>
            Error loading map: {e}
        </div>
    )
}

this did not work. The error is happening at build time. Not when the component is rendered.


Update #2

I tried using React's componentDidCatch and ErrorBoundary as seen in this blog post. But I think this error is happening during a build, not during a render. So how do I catch build errors and show an error message?

Frank
  • 735
  • 1
  • 12
  • 33
  • what about: `import * as google from 'react-google-maps'` – PlayMa256 Dec 10 '18 at 18:27
  • what would that accomplish? If anything that just gives me more failed modules @PlayMa256 – Frank Dec 10 '18 at 19:39
  • 1
    You say two contradictory things. First you say that it happens when your application goes offline (indicating a run time error), but then you mention that it is a build error. You can't catch run time errors at build time and you can't catch build errors at run time. Note that the error you are showing looks like a run time error, and almost exactly the same as [this question](https://stackoverflow.com/q/14229695/215552)... – Heretic Monkey Dec 11 '18 at 18:42
  • You're trying to use `google`, presumably a global, that isn't there. You should look into how to make it available either via globals or via `import`. – Madara's Ghost Dec 11 '18 at 19:09

1 Answers1

1

Try setting a google constant yourself. This will protect against runtime errors. Then you can conditionally render your online / offline components based on the presence of google.

const google = window.google || null;

return google ? (
  <Online />
) : (
  <Offline />
);

One thing to note is that you would have to guard anything that uses google so that it's only invoked when the <Online /> component is rendered.

Seth
  • 10,198
  • 10
  • 45
  • 68