Search code examples
javascriptreactjsmobxmobx-reactreact-google-maps

React: Convert HOC const to component


I am using React Google Maps to add Google Maps to my page, and I am setting up the map here:

import React from "react";
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";

export const MapWithMarkers = withScriptjs(withGoogleMap((props) =>
  <GoogleMap
    defaultZoom={17}
    center={{ lat: parseFloat(props.lat), lng: parseFloat(props.long) }}
  >
    {props.markers.map(marker => (
        <Marker
          key={marker.todoId}
          position={{ lat: parseFloat(marker.lat), lng: parseFloat(marker.long) }}
        />
    ))}
  </GoogleMap>
))

However, I would like to inject a store and use this.props.store.lat rather than props.lat, using @inject('store'), which requires MapWithMarkers to be turned into a class instead of the const.

I have tried the following:

import React from "react";
import { observer, inject } from 'mobx-react';
import PropTypes from 'prop-types';
import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";

@inject('store') @observer
export class MapWithMarkers extends React.Component {
  static propTypes = {
    store: PropTypes.object.isRequired,
  }

  constructor(props) {
    super(props);
  }

  renderMarkers = (props) => {
    <GoogleMap
      defaultZoom={17}
      center={{ lat: parseFloat(this.props.store.lat), lng: parseFloat(this.props.store.long) }}
    >
      {this.props.store.todos.map(marker => (
        <Marker
          key={marker.todoId}
          position={{ lat: parseFloat(marker.lat), lng: parseFloat(marker.long) }}
        />
      ))}
    </GoogleMap>
  }

  render() {
    const props = this.props;
    return withScriptjs(withGoogleMap(this.renderMarkers()));
  }

}

This is not working, returning:

Uncaught (in promise) Error: MapWithMarkers.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

What am I doing wrong?


Solution

  • withScriptjs & withGoogleMap are HOC, you should pass a HOC a component. So your component should look something like this:

    import React from "react";
    import { observer, inject } from 'mobx-react';
    import PropTypes from 'prop-types';
    import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps";
    
    @inject('store') @observer
    export class Map extends React.Component {
      static propTypes = {
        store: PropTypes.object.isRequired,
      }
    
      render() {
        return <GoogleMap
          defaultZoom={17}
          center={{ lat: parseFloat(this.props.store.lat), lng: parseFloat(this.props.store.long) }}
        >
          {this.props.store.todos.map(marker => (
            <Marker
              key={marker.todoId}
              position={{ lat: parseFloat(marker.lat), lng: parseFloat(marker.long) }}
            />
          ))}
        </GoogleMap>
      }
    
    }
    
    export const MapWithMarkers = withScriptjs(withGoogleMap(Map))