Skip to content

Commit 229c102

Browse files
heiskrCopilot
andauthored
⚙️ Bump react and react-dom to v19 (#60891)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 07510f6 commit 229c102

8 files changed

Lines changed: 68 additions & 74 deletions

File tree

package-lock.json

Lines changed: 45 additions & 60 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@
243243
"ora": "^9.3.0",
244244
"parse5": "7.1.2",
245245
"quick-lru": "7.0.1",
246-
"react": "^18.3.1",
247-
"react-dom": "^18.3.1",
246+
"react": "^19.2.5",
247+
"react-dom": "^19.2.5",
248248
"react-is": "^19.2.4",
249249
"react-markdown": "^10.1.0",
250250
"rehype-highlight": "^7.0.2",
@@ -297,8 +297,8 @@
297297
"@types/lodash": "^4.17.24",
298298
"@types/lodash-es": "4.17.12",
299299
"@types/mdast": "^4.0.4",
300-
"@types/react": "18.3.20",
301-
"@types/react-dom": "^18.3.7",
300+
"@types/react": "19.2.14",
301+
"@types/react-dom": "^19.2.3",
302302
"@types/semver": "^7.7.1",
303303
"@types/styled-components": "^5.1.36",
304304
"@types/tcp-port-used": "1.0.4",

src/frame/components/ui/BumpLink/BumpLink.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import styles from './BumpLink.module.scss'
55

66
export type BumpLinkPropsT = {
77
children?: ReactNode
8-
title: ReactElement | string
8+
title: ReactElement<{ children?: ReactNode }> | string
99
href: string
1010
as?: ElementType<{ className?: string; href: string }>
1111
className?: string

src/frame/components/ui/MarkdownContent/MarkdownContent.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReactNode } from 'react'
1+
import { memo, ReactNode } from 'react'
22
import type { JSX } from 'react'
33
import cx from 'classnames'
44

@@ -10,12 +10,15 @@ export type MarkdownContentPropsT = {
1010
as?: keyof JSX.IntrinsicElements
1111
}
1212

13-
export const MarkdownContent = ({
13+
// Memoized so that re-renders of the parent (e.g. when ToolPicker/PlatformPicker
14+
// state updates) don't cause React 19 to re-apply `dangerouslySetInnerHTML` and
15+
// wipe out the inline `display` styles set imperatively by the pickers.
16+
export const MarkdownContent = memo(function MarkdownContent({
1417
children,
1518
as: Component = 'div',
1619
className,
1720
...restProps
18-
}: MarkdownContentPropsT) => {
21+
}: MarkdownContentPropsT) {
1922
return (
2023
<Component
2124
{...restProps}
@@ -25,4 +28,4 @@ export const MarkdownContent = ({
2528
: { children })}
2629
/>
2730
)
28-
}
31+
})

src/search/components/input/SearchBarButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Props = {
1212
isSearchOpen: boolean
1313
setIsSearchOpen: (value: boolean) => void
1414
params: QueryParams
15-
searchButtonRef: React.RefObject<HTMLButtonElement>
15+
searchButtonRef: React.RefObject<HTMLButtonElement | null>
1616
instanceId?: string
1717
}
1818

src/search/components/input/SearchOverlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import styles from './SearchOverlay.module.scss'
3434

3535
type Props = {
3636
searchOverlayOpen: boolean
37-
parentRef: RefObject<HTMLElement>
37+
parentRef: RefObject<HTMLElement | null>
3838
debug: boolean
3939
onClose: () => void
4040
params: {

src/search/components/input/SearchOverlayContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type Props = {
77
setIsSearchOpen: (value: boolean) => void
88
params: QueryParams
99
updateParams: (updates: Partial<QueryParams>) => void
10-
searchButtonRef: React.RefObject<HTMLButtonElement>
10+
searchButtonRef: React.RefObject<HTMLButtonElement | null>
1111
}
1212

1313
export function SearchOverlayContainer({

src/tools/components/InArticlePicker.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react'
1+
import React, { useEffect, useLayoutEffect, useState } from 'react'
22
import Cookies from '@/frame/components/lib/cookies'
33
import { UnderlineNav } from '@primer/react'
44
import { sendEvent } from '@/events/components/events'
@@ -7,6 +7,8 @@ import { useRouter } from 'next/router'
77

88
import styles from './InArticlePicker.module.scss'
99

10+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect
11+
1012
type Option = {
1113
value: string
1214
label: string
@@ -63,7 +65,11 @@ export const InArticlePicker = ({
6365

6466
const [asPathRoot, asPathQuery = ''] = router.asPath.split('#')[0].split('?')
6567

66-
useEffect(() => {
68+
// Use a layout effect so the DOM mutation (hiding non-matching .ghd-tool
69+
// content) happens before the browser paints. With React 19's stricter
70+
// effect timing, a regular useEffect could leave non-matching content
71+
// visible on initial page load until after first paint.
72+
useIsomorphicLayoutEffect(() => {
6773
// This will make the hook run this callback on mount and on change.
6874
// That's important because even though the user hasn't interacted
6975
// and made an overriding choice, we still want to run this callback

0 commit comments

Comments
 (0)