'Map Marker don't show up (Marker rendered before Map)- ReactJS with @react-google-maps/api

What I want:

Having a Default ReactJS App with a Google Map

Problem:

Marker don't display

Possible reason:

Marker been added before map finish load.

Files:

App.js, (Default ReactJS file)

Map.js, (Customized ReactJS Component)

./style/map.css

Map.js:

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

import React from "react";
import "./style/map.css";

const Map = ({ zoomLevel, map_lat, map_lng, mark_lat, mark_lng }) => {
  const center = { lat: map_lat, lng: map_lng };

  const { isLoaded } = useLoadScript({
    googleMapsApiKey: "---USE API KEY HERE---",
  });

  //Return maps
  if (!isLoaded) {
    return <div>Loading...</div>;
  } else {
    return (
      <GoogleMap
        mapContainerClassName="map-container"
        zoom={zoomLevel}
        center={center}
        onLoad={() => {
          console.log("Map is loaded!");
        }}
      >
        {/* Debug Purpose */}
        {console.warn("Marker been added!")}

        {/* Add Marker */}
        <Marker position={{ lat: mark_lat, lng: mark_lng }} />
      </GoogleMap>
    );
  }
};

Map.defaultProps = {
  zoomLevel: 14,
  map_lat: 50,
  map_lng: -100,
  mark_lat: 50,
  mark_lng: -100,
};

export default Map;

Extra Information:

As you may noticed, I have console log and warn to tell the order of render, from my understanding,

Marker seems been added before Map fully loaded.

Debug Result: Marker been added before Map onLoad been called.

And I do managed render the marker on the map manually (local host):

  1. delete the Marker in run time and save changes, (So let the Map finish load first.)

  2. add Marker. (Map is already finished loading)

And now I got the marker, but it will not be here next time.

Manually Add Marker After Map Rendered, The Marker appear.



Solution 1:[1]

You are lucky, there is a cool algorithm due to van Herk, Gil and Werman that computes a 1D dilation in constant time per element.

https://tpgit.github.io/UnOfficialLeptDocs/leptonica/grayscale-morphology.html

It can be made online with a buffer of 2N-1 elements.

The idea is simple. If you want to compute the maxima of four successive elements, you can compute incrementally the following maxima: a, ab, abc, abcd and e, ef, efg, efgh. Now combine...

abcd
 bcd e
  cd ef
   d efg

and repeat with the following elements.

Solution 2:[2]

Thanks everyone. Here is my Java implementation of the Deque-based algorithm (


import java.util.*;

/**
 *  Calculation is exclusive, i.e. immediately after adding an entry, the entry is not under consideration for min/max. <br>
 *
 *  Algorith outline: <br>
 *     at every step: <br>
 *    <br>
 *       if (!Deque.Empty) and (Deque.Head.Index <= CurrentIndex - T) then        <br>
 *          Deque.ExtractHead;                                                    <br>
 *       //Head is too old, it is leaving the window                              <br>
 *                                                                                <br>
 *       while (!Deque.Empty) and (Deque.Tail.Value > CurrentValue) do            <br>
 *          Deque.ExtractTail;                                                    <br>
 *       //remove elements that have no chance to become minimum in the window    <br>
 *                                                                                <br>
 *       Deque.AddTail(CurrentValue, CurrentIndex);                               <br>
 *       CurrentMin = Deque.Head.Value                                            <br>
 *       //Head value is minimum in the current window                            <br>
 */
public class RollingMinMax {

    private static class Entry {
        final int index;
        final double value;

        private Entry(int index, double value) {
            this.index = index;
            this.value = value;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Entry{");
            sb.append("index=").append(index);
            sb.append(", value=").append(value);
            sb.append('}');
            return sb.toString();
        }
    }
    
    private final ArrayDeque<Entry> _minQueue;
    private final ArrayDeque<Entry> _maxQueue;
    private final int _windowSizeMin;
    private final int _windowSizeMax;
    private int _count= 0;
    private ArrayList<Double> _minHistory;
    private ArrayList<Double> _maxHistory;

    public RollingMinMax(int windowSizeMin, int windowSizeMax, boolean keepHistories) {
        _windowSizeMin = windowSizeMin;
        _windowSizeMax = windowSizeMax;
        if (_windowSizeMin < 0 || _windowSizeMax < 0) {
            throw new IllegalArgumentException("window size(s) too small");
        }
        _minQueue = new ArrayDeque<>(windowSizeMin);
        _maxQueue = new ArrayDeque<>(windowSizeMax);
        if (keepHistories) {
            _minHistory = new ArrayList<>();
            _maxHistory = new ArrayList<>();
        }
    }

    public void add(double datum) {
        final Entry entry = new Entry(_count, datum);

        // remove entriesthat are too old for consideration
        while (!_minQueue.isEmpty() && _minQueue.getFirst().index < _count - _windowSizeMin) {
            _minQueue.removeFirst();
        }
        while (!_maxQueue.isEmpty() && _maxQueue.getFirst().index < _count - _windowSizeMax) {
            _maxQueue.removeFirst();
        }

        // remove entries too small/large
        while (!_minQueue.isEmpty() && _minQueue.getLast().value > datum) {
            _minQueue.removeLast();
        }
        while (!_maxQueue.isEmpty() && _maxQueue.getLast().value < datum) {
            _maxQueue.removeLast();
        }

        enqueueCurrent(entry);

        ++_count;

        if (_minHistory != null) {
            _minHistory.add(getMin());
            _maxHistory.add(getMax());
        }

    }

    private void enqueueCurrent(Entry entry) {
        _minQueue.addLast(entry);
        _maxQueue.addLast(entry);
    }

    /** Double.NaN returned if not enough data added yet to compute. */
    public double getMin() {
        if (_count <= _windowSizeMin) {
            return Double.NaN;
        }
        double result = _minQueue.getFirst().value;
        return result;
    }

    public double getMax() {
        if (_count <= _windowSizeMax) {
            return Double.NaN;
        }
        double result = _maxQueue.getFirst().value;
        return result;
    }

    private ArrayList<Double> getMinHistory() {
        return _minHistory;
    }

    private ArrayList<Double> getMaxHistory() {
        return _maxHistory;
    }

    public String toString() {
        return "RollingMinMax[" + _windowSizeMin + ", "+ _windowSizeMax + "] min = " + getMin() + ", max =" + getMax() + ", count = " + _count;
    }

    public static void main(String[] ignored) {
        final ArrayList<Double> data = (ArrayList<Double>) Arrays.asList(
            1d, 4d, 6d,  0d, 9d, 5d, 3d, 6d, 8d, 10d, 13d, 15d, 8d, 14d, 12d, 5d, 6d, 8d, 10d, 7d, 5d, 3d, 2d
        );

        RollingMinMax calculator = new RollingMinMax(4, 6, true);
        System.out.println("calculator = " + calculator);

        int index = 0;
        for (double datum : data) {
            calculator.add(datum);
            System.out.println(index + "\t data=" + datum + ", min=" + calculator.getMin() + ", max=" +calculator.getMax());
            ++index;
        }
    }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 barneypitt