title: How to change the opacity of a GroundOverlay in react-google-maps?
body: <p>Using the <code>react-google-maps</code> example with the <code>GroundOverlay</code> component as an example (cf. <a href="https://github.com/khpeek/beomaps/blob/master/src/App.js" rel="nofollow noreferrer">https://github.com/khpeek/beomaps/blob/master/src/App.js</a>), I'd like to make a slider which changes the opacity of the overlay.</p>
  
  <p>For example, currently, if I render this component, I get an overlay with a fixed opacity of <code>0.5</code>:</p>
  
  <pre><code>/* global google */
  
  import React from "react"
  import { compose } from "recompose"
  import { 
    withScriptjs,
    withGoogleMap,
    GoogleMap,
    GroundOverlay } from "react-google-maps"
  
  export const MapWithGroundOverlay = compose(
    withScriptjs,
    withGoogleMap
  )(props =&gt;
    &lt;GoogleMap
      defaultZoom={12}
      defaultCenter={{lat: 40.740, lng: -74.18}}
    &gt;
      &lt;GroundOverlay
        defaultUrl="https://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg"
        defaultBounds={new google.maps.LatLngBounds(
          new google.maps.LatLng(40.712216, -74.22655),
          new google.maps.LatLng(40.773941, -74.12544)
        )}
        defaultOpacity={.5}
      /&gt;
    &lt;/GoogleMap&gt;
  );
  </code></pre>
  
  <p>which looks like this:</p>
  
  <p><a href="https://i.stack.imgur.com/j1NfP.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/j1NfP.jpg" alt="enter image description here"></a></p>
  
  <p>I'm struggling to see, however, how to change the opacity 'dynamically' with a slider. Ultimately, I believe I would have to call the <code>setOpacity</code> method on the instance of the <code>google.maps.GroundOverlay</code> class (cf. <a href="https://developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay" rel="nofollow noreferrer">https://developers.google.com/maps/documentation/javascript/reference/image-overlay#GroundOverlay</a>). However, if I look at the source code for the <code>&lt;GroundOverlay&gt;</code> component (cf. <a href="https://github.com/tomchentw/react-google-maps/blob/ca5c5c6f5346fb3ee0037893fbca488a408c9938/lib/components/GroundOverlay.js#L59" rel="nofollow noreferrer">https://github.com/tomchentw/react-google-maps/blob/ca5c5c6f5346fb3ee0037893fbca488a408c9938/lib/components/GroundOverlay.js#L59</a>),</p>
  
  <pre><code>var GroundOverlay = (exports.GroundOverlay = (function(_React$PureComponent) {
    ;(0, _inherits3.default)(GroundOverlay, _React$PureComponent)
  
    /*
     * @see https://developers.google.com/maps/documentation/javascript/3.exp/reference#GroundOverlay
     */
    function GroundOverlay(props, context) {
      ;(0, _classCallCheck3.default)(this, GroundOverlay)
  
      var _this = (0, _possibleConstructorReturn3.default)(
        this,
        (
          GroundOverlay.__proto__ || (0, _getPrototypeOf2.default)(GroundOverlay)
        ).call(this, props, context)
      )
  
      ;(0, _warning2.default)(
        !props.url || !props.bounds,
        "\nFor GroundOveray, url and bounds are passed in to constructor and are immutable\n after iinstantiated. This is the behavior of Google Maps JavaScript API v3 (\n See https://developers.google.com/maps/documentation/javascript/reference#GroundOverlay)\n Hence, use the corresponding two props provided by `react-google-maps`.\n They're prefixed with _default_ (defaultUrl, defaultBounds).\n\n In some cases, you'll need the GroundOverlay component to reflect the changes\n of url and bounds. You can leverage the React's key property to remount the\n component. Typically, just `key={url}` would serve your need.\n See https://github.com/tomchentw/react-google-maps/issues/655\n"
      )
      var groundOverlay = new google.maps.GroundOverlay(
        props.defaultUrl || props.url,
        props.defaultBounds || props.bounds
      )
      ;(0, _MapChildHelper.construct)(
        GroundOverlay.propTypes,
        updaterMap,
        _this.props,
        groundOverlay
      )
      groundOverlay.setMap(_this.context[_constants.MAP])
      _this.state = (0, _defineProperty3.default)(
        {},
        _constants.GROUND_LAYER,
        groundOverlay
      )
      return _this
    }
  
    ;(0, _createClass3.default)(GroundOverlay, [
      {
        key: "componentDidMount",
        value: function componentDidMount() {
          ;(0, _MapChildHelper.componentDidMount)(
            this,
            this.state[_constants.GROUND_LAYER],
            eventMap
          )
        },
      },
      {
        key: "componentDidUpdate",
        value: function componentDidUpdate(prevProps) {
          ;(0, _MapChildHelper.componentDidUpdate)(
            this,
            this.state[_constants.GROUND_LAYER],
            eventMap,
            updaterMap,
            prevProps
          )
        },
      },
      {
        key: "componentWillUnmount",
        value: function componentWillUnmount() {
          ;(0, _MapChildHelper.componentWillUnmount)(this)
          var GroundOverlay = this.state[_constants.GROUND_LAYER]
          if (GroundOverlay) {
            GroundOverlay.setMap(null)
          }
        },
      },
      {
        key: "render",
        value: function render() {
          return false
        },
  
        /**
         * Gets the `LatLngBounds` of this overlay.
         * @type LatLngBoundsLatLngBounds
         * @public
         */
      },
      {
        key: "getBounds",
        value: function getBounds() {
          return this.state[_constants.GROUND_LAYER].getBounds()
        },
  
        /**
         * Returns the opacity of this ground overlay.
         * @type number
         * @public
         */
      },
      {
        key: "getOpacity",
        value: function getOpacity() {
          return this.state[_constants.GROUND_LAYER].getOpacity()
        },
  
        /**
         * Gets the url of the projected image.
         * @type string
         * @public
         */
      },
      {
        key: "getUrl",
        value: function getUrl() {
          return this.state[_constants.GROUND_LAYER].getUrl()
        },
      },
    ])
    return GroundOverlay
  })(
    _react2.default.PureComponent
  )) /*
  </code></pre>
  
  <p>then it seems like it has only a <code>getOpacity()</code> method, but no <code>setOpacity()</code> one. Also, the <code>groundOverlay</code> variable is a local variable of the <code>function GroundOverlay(props, context)</code>, so I don't see how I could access its <code>setOpacity</code> method.</p>
  
  <p>Any ideas on how to approach this?</p>
  
  <h3>Update</h3>
  
  <p>I've noticed that the <code>GroundOverlay</code> component accepts an <code>opacity</code> prop which determines its opacity. Using this, I tried to create a component <code>AdjustableGroundoverlay</code> containing both a <code>&lt;GroundOverlay&gt;</code> and a <code>&lt;button&gt;</code> (for now) to change the <code>GroundOverlay</code>'s opacity:</p>
  
  <pre><code>import React from "react"
  import { MapWithGroundOverlay } from "./MapWithGroundOverlay"
  
  export class AdjustableGroundoverlay extends React.PureComponent {
    constructor(props, context) {
      super(props, context)
      this.state = {opacity: 0.5}
      this.handleClick = this.handleClick.bind(this);
    }
  
    handleClick() {
      this.setState(state =&gt; ({
        opacity: 1.0
      }));
    }
  
    render() {
      return (
        &lt;div&gt;
          &lt;MapWithGroundOverlay
            googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&amp;v=3.exp&amp;libraries=geometry,drawing,places`}
            loadingElement={&lt;div style={{ height: `100%` }} /&gt;}
            containerElement={&lt;div style={{ height: `600px` }} /&gt;}
            mapElement={&lt;div style={{ height: `100%` }} /&gt;}
            opacity={this.state.opacity}
          /&gt;
          &lt;button onClick={this.handleClick}&gt;
            {`Opacity: ${this.state.opacity}`}
          &lt;/button&gt;
        &lt;/div&gt;
      );
    }
  }
  </code></pre>
  
  <p>However, I've noticed that when I click the button, although its label changes from <code>Opacity: 0.5</code> to <code>Opacity: 1</code>, the actual opacity of the overlay doesn't change:</p>
  
  <p><a href="https://i.stack.imgur.com/rz16D.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rz16D.jpg" alt="enter image description here"></a></p>
  
  <p>As I understand from <a href="https://reactjs.org/docs/handling-events.html" rel="nofollow noreferrer">https://reactjs.org/docs/handling-events.html</a>, calling <code>setState()</code> on the <code>AdjustableGroundoverlay</code> should cause it to call its <code>render()</code> method again, thereby passing the new <code>this.state.opacity</code> as a prop to <code>GroundOverlay</code> and changing its opacity. I don't understand why this is not working?</p>