visgl / visgl/react-map-gl

[Bug] Invalid type: 'container' must be a String or HTMLElement.

Open
#1,960 13 comments 7 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
8.5k
Forks
1.4k
Avg merge
5d 17h
Merged PRs (30d)
3

Description

Description

We get an error "Invalid type: 'container' must be a String or HTMLElement." under certain circumstances which are flaky and unclear. The stack trace points to react-map-gl, but this is using a error logging system and local reproduction has not proven successful.

Here is my theory as to what is happening (note: it was difficult to find documentation regarding the React lifecycle as it pertains to what is mentioned below):

  1. The Map mounts, which kicks off the library load, and that is in progress
  2. Now, Map begins an unmount for whatever reason.
  3. containerRef.current gets set to null as part of the unmount
  4. The library load finishes, and hence the rest of the promise runs. It checks isMounted, which is still set to true, and hence continues running. It runs mapbox = new Mapbox(mapboxgl.Map, props, containerRef.current);, which fails with the above error as containerRef.current is null.
  5. The useEffect cleanup function runs and sets isMounted to false, which would have made the promise stop running, but alas too late.

Now whether this theory works depends on at least two things

  1. Refs getting nulled out before useEffect cleanup is run
  2. async code being able to run between the ref clearing and useEffect cleanup happening

I don't know about the second point, but an experiment with React (17.0.2) roughly as follows

  useEffect(() => {
    console.log('XXX USE EFFECT');
    return () => {
      console.log('XXX USE EFFECT CLEANUP');
    }
  }, []);

  return <div ref={(item) => console.log('XXX SET REF', item)} />;

prints

  • XXX SET REF <div>
  • XXX USE EFFECT
    [navigate away]
  • XXX SET REF null
  • XXX USE EFFECT CLEANUP

which seems to support that refs are cleared before useEffect cleanups are run.

Assuming this theory seems plausible, it perhaps would be better to check for the presence of containerRef.current in addition to the isMounted check. (from what I can tell, containerRef is guaranteed to be set from the first render before useEffect runs, so long as it doesn't get cleared by an unmount)

Expected Behavior

No error message

Steps to Reproduce

Unknown :(

Environment
  • Framework version: react-map-gl@7.0.15
  • Map library: mapbox-gl@2.8.1
  • Browser: Various, including Chrome 104.0.0
  • OS: Various, including Windows 10
Logs

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no files or tests; start by tracing the Map mount/unmount lifecycle and the asynchronous library-load path around containerRef.current and isMounted. Reproduce or isolate the reported race, then verify that unmounting during loading no longer produces the invalid-container error.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.