[Bug] Invalid type: 'container' must be a String or HTMLElement.
Nobody has claimed this yet.
- 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):
- The Map mounts, which kicks off the library load, and that is in progress
- Now, Map begins an unmount for whatever reason.
containerRef.currentgets set to null as part of the unmount- 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 runsmapbox = new Mapbox(mapboxgl.Map, props, containerRef.current);, which fails with the above error ascontainerRef.currentis null. - The useEffect cleanup function runs and sets
isMountedto false, which would have made the promise stop running, but alas too late.
Now whether this theory works depends on at least two things
- Refs getting nulled out before useEffect cleanup is run
- 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 nullXXX 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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