0

Good evening.

The purpose of this component is to create a map taking data from observable curentLocation. loadInitialLocation() and newMap() in useEffect() should only be called once, and updateMap() in autorun() is called whenever the obrservable curentLocation changes.

The issue is: newMap() shouldn't be called until loadInitialLocation() finishes its job which is to get data from server and load the result into observable curentLocation. Now newMap() is called when obrservable curentLocation is null.

I tried this in the useEffect():

useEffect(() => {
    loadInitialLocation().then(newMap());
  }, []);

where constant loadInitialLocation:() => Promise<void>. I expected that "newMap() will run only when loadInitialLocation() is done".

I also tried this in useEffect():

useEffect(() => {
    const getCurLoc = async () => {
      await loadInitialLocation();
      newMap();
    }
    getCurLoc();
  }, []);

and this:

useEffect(() => {
    loadInitialLocation().then(newMap());
    autorun(() => {
      console.log("autorun here")
      updateMap();
    });
  }, []);

the store:

@observable currentLocation: ILocation | null = null;
@action loadInitialLocation = async () => {
      try {
        const currentLocation = await agent.Adventure.locationDetails();
        runInAction(() => {
          this.currentLocation = currentLocation;
          console.log("load currentLocation")
        });
      } catch (error) {
        throw error;
      }
    }
  };

the component:

const LeafletMap: React.FC = () => {
  var map: L.Map;
  const tilePixelSize = 32;
  const rootStore = useContext(RootStoreContext);
  const { openModal } = rootStore.modalStore;
  const { currentLocation, loadInitialLocation } = rootStore.mapStore;

  useEffect(() => {
    loadInitialLocation().then(newMap());
  }, []);

  autorun(() => {
    console.log("autorun here")
    updateMap();
  });

  const newMap = () => {
    if (currentLocation == null) {
      console.log("null currentLocation");
      return null;
    }
    // code
    // use currentLocation to load the initial map

    console.log("successfully init map");
  };

  const updateMap = () => {
    if (map == undefined) {
      return null;
    }
    console.log("update map");
    // code
  };
  console.log("add to dom");
  return <div id="map"></div>;
};

export default observer(LeafletMap);

If I move to any other page and come back to this, the map will be loaded correctly. I think it's because that the oberservable currentLocation is loaded, and hence the newMap() won't reach if (currentLocation == null) and return null.

How do I ensure that only runs newMap() after loadInitialLocation() is done? Am I not using async, await, and then correctly?

nkforce
  • 29
  • 2
  • 9

1 Answers1

0

I didn't use the right way to call newMap()

This should be the correct way:

useEffect(() => {
    loadInitialLocation().then(() => newMap());
  }, []);

By this, we can assure that we can do "then" only when we get an expected result from mobx action.

useEffect(() => {
    loadInitialLocation().then((result) => {
      if (result) {
        newMap(result);
      }
    });
  }, [loadInitialLocation])
nkforce
  • 29
  • 2
  • 9