Skip to content

[RFC] Migrate 70 deprecated React APIs to modern equivalents #1106

@Codingkhushi

Description

@Codingkhushi

Summary

I've scanned the codebase using an automated React deprecation detector and found 70 deprecated APIs across 49 files that need migration for React 18+ compatibility.

Findings

Legacy Context API (50 issues - 71%)

The project extensively uses the deprecated Context API (contextTypes, getChildContext, childContextTypes) which was deprecated in React 16.3 and will be removed in React 19.

Affected files: Nearly every component

Deprecated Lifecycle Methods (7 issues)

  • componentWillMount (5 occurrences)
  • componentWillUpdate (2 occurrences)

Affected files: InfoWindow, InfoBox, SearchBox

React 18 Rendering Methods (9 issues)

  • ReactDOM.unmountComponentAtNode (9 occurrences)

Affected files: InfoWindow, OverlayView, InfoBox, MarkerWithLabel, SearchBox

DOM Methods (2 issues)

  • ReactDOM.findDOMNode (2 occurrences)

Affected files: StandaloneSearchBox

Factory Pattern (2 issues)

  • React.createFactory (2 occurrences)

Affected files: withGoogleMap, withScriptjs

Impact

  • ⚠️ React 19 compatibility risk - Legacy Context API will be removed
  • ⚠️ React 18 warnings - Deprecated methods trigger console warnings
  • ⚠️ Future-proofing - Migrating now ensures compatibility with future React versions

Proposed Solution

I can help migrate these in stages:

  1. Phase 1: Migrate simple lifecycle methods (2 auto-fixable)
  2. Phase 2: Migrate ReactDOM methods (9 instances)
  3. Phase 3: Migrate Legacy Context API (requires refactoring - this is the big one)

Would the maintainers be interested in accepting PRs for this migration?

Scan Report

Full scan output (70 issues)

📋 Issues by Category:

📦 context (50 issues):
⚠️ BicyclingLayer.jsx:28 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Circle.jsx:153 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ DirectionsRenderer.jsx:73 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ FusionTablesLayer.jsx:43 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ GoogleMap.jsx:211 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ GroundOverlay.jsx:71 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ InfoWindow.jsx:86 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ KmlLayer.jsx:73 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:306 - getChildContext
Deprecated: Legacy Context API (getChildContext)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:284 - childContextTypes
Deprecated: Legacy Context API (childContextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:279 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ OverlayView.jsx:63 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Polygon.jsx:143 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Polyline.jsx:133 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Rectangle.jsx:138 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:170 - getChildContext
Deprecated: Legacy Context API (getChildContext)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:152 - childContextTypes
Deprecated: Legacy Context API (childContextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:148 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ TrafficLayer.jsx:38 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ InfoBox.jsx:89 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ MarkerClusterer.jsx:234 - getChildContext
Deprecated: Legacy Context API (getChildContext)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ MarkerClusterer.jsx:211 - childContextTypes
Deprecated: Legacy Context API (childContextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ MarkerClusterer.jsx:207 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ MarkerWithLabel.jsx:316 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ DrawingManager.jsx:79 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ SearchBox.jsx:55 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ HeatmapLayer.jsx:49 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ BicyclingLayer.jsx:30 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Circle.jsx:39 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ DirectionsRenderer.jsx:30 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ FusionTablesLayer.jsx:30 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ GoogleMap.jsx:47 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ GroundOverlay.jsx:53 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ InfoWindow.jsx:38 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ KmlLayer.jsx:31 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:70 - getChildContext
Deprecated: Legacy Context API (getChildContext)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:48 - childContextTypes
Deprecated: Legacy Context API (childContextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Marker.jsx:43 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ OverlayView.jsx:60 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Polygon.jsx:39 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Polyline.jsx:39 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ Rectangle.jsx:39 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:53 - getChildContext
Deprecated: Legacy Context API (getChildContext)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:35 - childContextTypes
Deprecated: Legacy Context API (childContextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ StreetViewPanorama.jsx:31 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ TrafficLayer.jsx:30 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ MarkerWithLabel.jsx:76 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ DrawingManager.jsx:37 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ SearchBox.jsx:41 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

⚠️ HeatmapLayer.jsx:31 - contextTypes
Deprecated: Legacy Context API (contextTypes)
💡 Use React.createContext(), Context.Provider, and static contextType or useContext

📦 lifecycleMethods (7 issues):
⚠️ InfoWindow.jsx:104 - componentWillMount
Deprecated LifeCycle Api componentWillMount
💡 Use constructor or componentDidMount (or useEffect in functional components)

⚠️ InfoBox.jsx:101 - componentWillMount
Deprecated LifeCycle Api componentWillMount
💡 Use constructor or componentDidMount (or useEffect in functional components)

⚠️ SearchBox.jsx:63 - componentWillMount
Deprecated LifeCycle Api componentWillMount
💡 Use constructor or componentDidMount (or useEffect in functional components)

⚠️ SearchBox.jsx:88 - componentWillUpdate
Deprecated LifeCycle Api componentWillUpdate
💡 Use getSnapshotBeforeUpdate or componentDidUpdate / useEffect

⚠️ InfoWindow.jsx:56 - componentWillMount
Deprecated LifeCycle Api componentWillMount
💡 Use constructor or componentDidMount (or useEffect in functional components)

⚠️ SearchBox.jsx:49 - componentWillMount
Deprecated LifeCycle Api componentWillMount
💡 Use constructor or componentDidMount (or useEffect in functional components)

⚠️ SearchBox.jsx:74 - componentWillUpdate
Deprecated LifeCycle Api componentWillUpdate
💡 Use getSnapshotBeforeUpdate or componentDidUpdate / useEffect

📦 rendering (9 issues):
⚠️ InfoWindow.jsx:155 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ OverlayView.jsx:130 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ InfoBox.jsx:154 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ MarkerWithLabel.jsx:382 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ SearchBox.jsx:117 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ InfoWindow.jsx:107 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ OverlayView.jsx:127 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ MarkerWithLabel.jsx:142 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

⚠️ SearchBox.jsx:103 - ReactDOM.unmountComponentAtNode
Deprecated: ReactDOM.unmountComponentAtNode
💡 Use root.unmount() via createRoot

📦 domMethods (2 issues):
⚠️ StandaloneSearchBox.jsx:56 - findDOMNode
Deprecated: ReactDOM.findDOMNode()
💡 Use refs to access DOM nodes directly

⚠️ StandaloneSearchBox.jsx:43 - findDOMNode
Deprecated: ReactDOM.findDOMNode()
💡 Use refs to access DOM nodes directly

📦 factory (2 issues):
⚠️ withGoogleMap.jsx:11 - React.createFactory
Deprecated: React.createFactory()
💡 Use JSX / React.createElement directly

⚠️ withScriptjs.jsx:13 - React.createFactory
Deprecated: React.createFactory()
💡 Use JSX / React.createElement directly

======================================================================

🔧 Step 2: Generating fixes...

📊 Fix Statistics:
High confidence: 2
Medium confidence: 0
Low confidence: 10

📝 Preview of changes:

❌ InfoWindow.jsx:104 [LOW]
Deprecated: componentWillMount
Action: manual-review
Before:
componentWillMount() {
if (!canUseDOM || this.containerElement) {
return
}
if (React.version.match(/^16/)) {
this.containerElement = document.createElement(div)
}
}
After:
// MANUAL REVIEW: Complex componentWillMount requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ Marker.jsx:306 [LOW]
Deprecated: getChildContext
Action: manual-review
Before:
getChildContext() {
return {
[ANCHOR]: this.context[ANCHOR] || this.state[MARKER],
}
}
After:
// MANUAL REVIEW: Complex getChildContext requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ StreetViewPanorama.jsx:170 [LOW]
Deprecated: getChildContext
Action: manual-review
Before:
getChildContext() {
return {
[MAP]: this.context[MAP].getStreetView(),
}
}
After:
// MANUAL REVIEW: Complex getChildContext requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ InfoBox.jsx:101 [LOW]
Deprecated: componentWillMount
Action: manual-review
Before:
componentWillMount() {
if (!canUseDOM || this.state[INFO_BOX]) {
return
}
const {
InfoBox: GoogleMapsInfobox,
} = require(/* "google-maps-infobox" uses "google" as a global variable. Since we don't
* have "google" on the server, we can not use it in server-side rendering.
* As a result, we import "google-maps-infobox" here to prevent an error on
* a isomorphic server.
*/ google-maps-infobox)
const infoBox = new GoogleMapsInfobox()
construct(InfoBox.propTypes, updaterMap, this.props, infoBox)
infoBox.setMap(this.context[MAP])
this.setState({
[INFO_BOX]: infoBox,
})
}
After:
// MANUAL REVIEW: Complex componentWillMount requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ MarkerClusterer.jsx:234 [LOW]
Deprecated: getChildContext
Action: manual-review
Before:
getChildContext() {
const markerClusterer = this.state[MARKER_CLUSTERER]
return {
[ANCHOR]: markerClusterer,
[MARKER_CLUSTERER]: markerClusterer,
}
}
After:
// MANUAL REVIEW: Complex getChildContext requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ SearchBox.jsx:63 [LOW]
Deprecated: componentWillMount
Action: manual-review
Before:
componentWillMount() {
if (!canUseDOM || this.containerElement) {
return
}
invariant(
google.maps.places,
Did you include "libraries=places" in the URL?
)
this.containerElement = document.createElement(div)
this.handleRenderChildToContainerElement()
if (React.version.match(/^16/)) {
return
}
this.handleInitializeSearchBox()
}
After:
// MANUAL REVIEW: Complex componentWillMount requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

✅ SearchBox.jsx:88 [HIGH]
Deprecated: componentWillUpdate
Action: rename
Before:
componentWillUpdate(nextProp) {
if (this.props.controlPosition !== nextProp.controlPosition) {
this.handleUnmountAtControlPosition()
}
}
After:
componentDidUpdate(nextProp) {
if (this.props.controlPosition !== nextProp.controlPosition) {
this.handleUnmountAtControlPosition()
}
}

❌ InfoWindow.jsx:56 [LOW]
Deprecated: componentWillMount
Action: manual-review
Before:
componentWillMount() {
if (!canUseDOM || this.containerElement) {
return
}
if (React.version.match(/^16/)) {
this.containerElement = document.createElement(div)
}
}
After:
// MANUAL REVIEW: Complex componentWillMount requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ Marker.jsx:70 [LOW]
Deprecated: getChildContext
Action: manual-review
Before:
getChildContext() {
return {
[ANCHOR]: this.context[ANCHOR] || this.state[MARKER],
}
}
After:
// MANUAL REVIEW: Complex getChildContext requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ StreetViewPanorama.jsx:53 [LOW]
Deprecated: getChildContext
Action: manual-review
Before:
getChildContext() {
return {
[MAP]: this.context[MAP].getStreetView(),
}
}
After:
// MANUAL REVIEW: Complex getChildContext requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

❌ SearchBox.jsx:49 [LOW]
Deprecated: componentWillMount
Action: manual-review
Before:
componentWillMount() {
if (!canUseDOM || this.containerElement) {
return
}
invariant(
google.maps.places,
Did you include "libraries=places" in the URL?
)
this.containerElement = document.createElement(div)
this.handleRenderChildToContainerElement()
if (React.version.match(/^16/)) {
return
}
this.handleInitializeSearchBox()
}
After:
// MANUAL REVIEW: Complex componentWillMount requires careful migration
// See: https://react.dev/reference/react/Component#componentwillreceiveprops

✅ SearchBox.jsx:74 [HIGH]
Deprecated: componentWillUpdate
Action: rename
Before:
componentWillUpdate(nextProp) {
if (this.props.controlPosition !== nextProp.controlPosition) {
this.handleUnmountAtControlPosition()
}
}
After:
componentDidUpdate(nextProp) {
if (this.props.controlPosition !== nextProp.controlPosition) {
this.handleUnmountAtControlPosition()
}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions