I'm working on a project using React 18 and Leaflet. (I don't believe Leaflet is part of the problem but it might be worth mentioning.) I'm trying to add custom elements to the map, but using createRoot gives me TypeError: m.createRoot is not a function
.
The code sample of what i'm trying to use is here:
import { MutableRefObject, ReactElement, useEffect } from 'react'
import L, { Map } from 'leaflet'
import { createRoot } from 'react-dom/client'
interface MapControlElementProps {
mapRef: MutableRefObject<Map | null>
button: ReactElement
position: L.ControlPosition
}
export default function TestElement(props: MapControlElementProps) {
useEffect(() => {
const { mapRef, button, position } = props
if (mapRef.current) {
const MapHelp = L.Control.extend({
onAdd: () => {
const controlElement = L.DomUtil.create(
'div',
'leaflet-control leaflet-bar'
)
const root = createRoot(controlElement)
root.render(button)
return controlElement
},
})
const control = new MapHelp({ position })
control.addTo(mapRef.current)
return () => {
control.remove()
}
}
return () => {}
}, [props])
return null
}
The only thing that works is using
ReactDOM.render(button, controlElement)
But tests are complaining about that:
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
Although ReactDOM.render works, I would much prefer to use createRoot because i'm using 18 everywhere else.
Update to the situation 2nd of March 2023
So far i have tracked the issue to react-dom package, react-dom/client.js where there is this code:
'use strict';
var m = require('react-dom');
if (process.env.NODE_ENV === 'production') {
exports.createRoot = m.createRoot;
exports.hydrateRoot = m.hydrateRoot;
} else {
var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
exports.createRoot = function(c, o) {
i.usingClientEntryPoint = true;
try {
return m.createRoot(c, o);
} finally {
i.usingClientEntryPoint = false;
}
};
exports.hydrateRoot = function(c, h, o) {
i.usingClientEntryPoint = true;
try {
return m.hydrateRoot(c, h, o);
} finally {
i.usingClientEntryPoint = false;
}
};
}
First of all, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED seems like an odd choice for name if this was indeed meant to be published but what do i know. However, a bit of poking around shows me that var m indeed doesn't have a function called createRoot. What to do with this now, i still don't know.