Skip to content

Commit

Permalink
[React@18] Upgrade @types to React 18 (#194144)
Browse files Browse the repository at this point in the history
## Summary

Part of #138222

This PR finilizes the breaking type fixes that are needed for upgrade to
React@18.
Most of the remaining issues are muted with "@ts-expect-error" are
tricky or could be runtime bugs that need to be looked at.

**Since the types changes are backward compatible (except the new APIs)
we can upgrade to @types/react@18 now so that we "save" the progress and
all the code in Kibana from now on is written in compatbile for react@18
way from types perspective.**
  • Loading branch information
Dosant authored Oct 1, 2024
1 parent dfe00f2 commit bdd57b6
Show file tree
Hide file tree
Showing 55 changed files with 157 additions and 81 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@
"**/hoist-non-react-statics": "^3.3.2",
"**/isomorphic-fetch/node-fetch": "^2.6.7",
"**/langchain": "^0.2.11",
"**/react-intl/**/@types/react": "^17.0.45",
"**/remark-parse/trim": "1.0.1",
"**/sharp": "0.32.6",
"**/typescript": "5.1.6",
"@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.cd77847.0",
"@types/react": "~18.2.0",
"@types/react-dom": "~18.2.0",
"globby/fast-glob": "^3.2.11"
},
"dependencies": {
Expand Down Expand Up @@ -1607,8 +1608,8 @@
"@types/pngjs": "^3.4.0",
"@types/prop-types": "^15.7.5",
"@types/rbush": "^3.0.0",
"@types/react": "^17.0.45",
"@types/react-dom": "^17.0.17",
"@types/react": "~18.2.0",
"@types/react-dom": "~18.2.0",
"@types/react-grid-layout": "^1.3.2",
"@types/react-is": "^17.0.3",
"@types/react-recompose": "^0.33.4",
Expand All @@ -1622,6 +1623,7 @@
"@types/react-window-infinite-loader": "^1.0.9",
"@types/redux-actions": "^2.6.1",
"@types/resolve": "^1.20.1",
"@types/scheduler": "^0.23.0",
"@types/seedrandom": ">=2.0.0 <4.0.0",
"@types/selenium-webdriver": "^4.1.26",
"@types/semver": "^7.5.8",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ interface State {

const convertToEui = (toast: ToastWithRichTitle): EuiToast => ({
...toast,
// @ts-expect-error upgrade typescript v5.1.6
title: toast.title instanceof Function ? <MountWrapper mount={toast.title} /> : toast.title,
text: toast.text instanceof Function ? <MountWrapper mount={toast.text} /> : toast.text,
});
Expand Down
5 changes: 4 additions & 1 deletion packages/core/overlays/core-overlays-browser/src/flyout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export interface OverlayFlyoutStart {
/**
* @public
*/
export type OverlayFlyoutOpenOptions = Omit<EuiFlyoutProps | EuiFlyoutResizableProps, 'onClose'> & {
export type OverlayFlyoutOpenOptions = Omit<
EuiFlyoutProps | EuiFlyoutResizableProps,
'onClose' | 'onResize'
> & {
/**
* EuiFlyout onClose handler.
* If provided the consumer is responsible for calling flyout.close() to close the flyout;
Expand Down
7 changes: 7 additions & 0 deletions packages/kbn-eslint-config/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ module.exports = {
from: 'rison-node',
to: '@kbn/rison',
},
{
from: 'react-dom/client',
to: 'react-dom',
exact: true,
disallowedMessage:
'Use `react-dom` instead of `react-dom/client` until upgraded to React 18',
},
],
],

Expand Down
4 changes: 2 additions & 2 deletions packages/kbn-esql-editor/src/esql_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export const ESQLEditor = memo(function ESQLEditor({
const editor1 = useRef<monaco.editor.IStandaloneCodeEditor>();
const containerRef = useRef<HTMLElement>(null);

const onMouseDownResize = useCallback(
const onMouseDownResize = useCallback<typeof onMouseDownResizeHandler>(
(
mouseDownEvent,
firstPanelHeight,
Expand All @@ -270,7 +270,7 @@ export const ESQLEditor = memo(function ESQLEditor({
[]
);

const onKeyDownResize = useCallback(
const onKeyDownResize = useCallback<typeof onKeyDownResizeHandler>(
(
keyDownEvent,
firstPanelHeight,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ export const ResizableContainer: React.FC<ResizableContainerProps> = memo(
);

const onWidthChange = useCallback(
(newSizes) =>
(newSizes: { [key: string]: number }) =>
dispatch(
changeUserSectionWidthsAction({
...newSizes,
...(newSizes as { left: number; right: number }),
savedToLocalStorage: true,
})
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useCallback, useEffect, useState, useRef, useMemo } from 'react';
import React, { useCallback, useEffect, useState, useRef, useMemo, ComponentProps } from 'react';
import {
EuiFlyout,
useEuiTheme,
Expand Down Expand Up @@ -45,7 +45,9 @@ function DocumentationFlyout({

const scrollTargets = useRef<Record<string, HTMLElement>>({});

const onNavigationChange = useCallback((selectedOptions) => {
const onNavigationChange = useCallback<
NonNullable<ComponentProps<typeof DocumentationNavigation>>['onNavigationChange']
>((selectedOptions) => {
setSelectedSection(selectedOptions.length ? selectedOptions[0].label : undefined);
if (selectedOptions.length) {
const scrollToElement = scrollTargets.current[selectedOptions[0].label];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import React, { useCallback, useState, useRef, useMemo, useEffect } from 'react';
import React, { useCallback, useState, useRef, useMemo, useEffect, ComponentProps } from 'react';
import { css } from '@emotion/react';
import { useEuiTheme, euiScrollBarStyles, EuiSpacer } from '@elastic/eui';
import { getFilteredGroups } from '../../utils/get_filtered_groups';
Expand Down Expand Up @@ -43,7 +43,9 @@ function DocumentationInline({ searchInDescription, height }: DocumentationInlin
return getFilteredGroups(searchText, searchInDescription, documentationSections, 1);
}, [documentationSections, searchText, searchInDescription]);

const onNavigationChange = useCallback((selectedOptions) => {
const onNavigationChange = useCallback<
NonNullable<ComponentProps<typeof DocumentationNavigation>>['onNavigationChange']
>((selectedOptions) => {
setSelectedSection(selectedOptions.length ? selectedOptions[0].label : undefined);
if (selectedOptions.length) {
const scrollToElement = scrollTargets.current[selectedOptions[0].label];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ export const FieldDescription = <T extends SettingType>({
* Justification for dangerouslySetInnerHTML:
* Setting description may contain formatting and links to documentation.
*/
/* @ts-expect-error upgrade typescript v5.1.6 */
dangerouslySetInnerHTML={{ __html: content || '' }} // eslint-disable-line react/no-danger
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,13 @@
*/

import React from 'react';
import {
EuiDataGridCustomToolbarProps,
EuiDataGridToolBarVisibilityOptions,
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
import { EuiDataGridCustomToolbarProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import './render_custom_toolbar.scss';

export interface UnifiedDataTableRenderCustomToolbarProps {
toolbarProps: EuiDataGridCustomToolbarProps;
gridProps: {
additionalControls?: EuiDataGridToolBarVisibilityOptions['additionalControls'];
additionalControls?: React.ReactNode;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const renderDataTable = async (props: Partial<UnifiedDataTableProps>) => {
// to "Can't perform a React state update on an unmounted component." warnings in tests,
// so we need to wait for the next animation frame to avoid this
await screen.findByTestId('discoverDocTable');
await act(() => new Promise((resolve) => requestAnimationFrame(() => resolve())));
await act(() => new Promise((resolve) => requestAnimationFrame(() => resolve(void 0))));
};

async function getComponent(props: UnifiedDataTableProps = getProps()) {
Expand Down Expand Up @@ -1107,7 +1107,7 @@ describe('UnifiedDataTable', () => {
// to "Can't perform a React state update on an unmounted component." warnings in tests,
// so we need to wait for the next animation frame to avoid this
await screen.findByTestId('unifiedDataTableCompareDocuments');
await act(() => new Promise((resolve) => requestAnimationFrame(() => resolve())));
await act(() => new Promise((resolve) => requestAnimationFrame(() => resolve(void 0))));
};

const getFullScreenButton = () => screen.queryByTestId('dataGridFullScreenButton');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const actWithTimeout = (action: Function, timer: number = 1) =>
new Promise((resolve) =>
setTimeout(async () => {
await action();
resolve();
resolve(void 0);
}, timer)
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ describe('MetricVisComponent', function () {
componentWithSecondaryDimension
.find(Metric)
.props()
// @ts-expect-error @types/react@18 - Parameter 'datum' implicitly has an 'any' type.
.data?.[0].map((datum) => datum?.extra)
).toMatchInlineSnapshot(`
Array [
Expand Down Expand Up @@ -602,6 +603,7 @@ describe('MetricVisComponent', function () {
componentWithExtraText
.find(Metric)
.props()
// @ts-expect-error @types/react@18 - Parameter 'datum' implicitly has an 'any' type.
.data?.[0].map((datum) => datum?.extra)
).toMatchInlineSnapshot(`
Array [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const actWithTimeout = (action: Function, timer: number = 1) =>
new Promise((resolve) =>
setTimeout(async () => {
await action();
resolve();
resolve(void 0);
}, timer)
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const AgentIcon = dynamic(() => import('@kbn/custom-icons/src/components/agent_i

export const getServiceNameCell =
(serviceNameField: string) => (props: DataGridCellValueElementProps) => {
const serviceNameValue = getFieldValue(props.row, serviceNameField);
const serviceNameValue = getFieldValue(props.row, serviceNameField) as string;
const agentName = getFieldValue(props.row, AGENT_NAME_FIELD) as AgentName;

if (!serviceNameValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jest
});

describe('useAdditionalCellActions', () => {
const initialProps: Parameters<typeof useAdditionalCellActions>[0] = {
const initialProps: React.PropsWithChildren<Parameters<typeof useAdditionalCellActions>[0]> = {
dataSource: createEsqlDataSource(),
dataView: dataViewWithTimefieldMock,
query: { esql: `FROM ${dataViewWithTimefieldMock.getIndexPattern()}` },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { Fragment, ReactChildren } from 'react';
import React, { Fragment } from 'react';
import { EuiFormRow, EuiSpacer, EuiCheckableCard, useGeneratedHtmlId } from '@elastic/eui';

import { FieldHook, getFieldValidityAndErrorMessage } from '../../hook_form_lib';
Expand All @@ -17,7 +17,7 @@ interface Props {
options: Array<{
label: string;
value: string;
children: ReactChildren;
children: React.ReactNode;
'data-test-subj'?: string;
}>;
euiFieldProps?: Record<string, any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const FloatingActions: FC<FloatingActionsProps> = ({
trigger: panelHoverTrigger,
};
const actions = (await getTriggerCompatibleActions(PANEL_HOVER_TRIGGER, context))
.filter((action): action is Action & { MenuItem: React.FC } => {
.filter((action): action is Action & { MenuItem: React.FC<{ context: unknown }> } => {
return action.MenuItem !== undefined && (disabledActions ?? []).indexOf(action.id) === -1;
})
.sort((a, b) => (a.order || 0) - (b.order || 0));
Expand All @@ -66,7 +66,6 @@ export const FloatingActions: FC<FloatingActionsProps> = ({
setFloatingActions(
<>
{actions.map((action) =>
// @ts-expect-error upgrade typescript v5.1.6
React.createElement(action.MenuItem, {
key: action.id,
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export function openContextMenu(
<KibanaRenderContextProvider analytics={getAnalytics()} i18n={getI18n()} theme={getTheme()}>
<EuiPopover
className="embPanel__optionsMenuPopover"
// @ts-expect-error @types/react@18 upgrade - Type 'HTMLElement' is not assignable to type 'NonNullable<ReactNode> | undefined'
button={container}
isOpen={true}
closePopover={onClose}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ interface Props {
export const DocumentEntryEditor: React.FC<Props> = React.memo(({ entry, setEntry }) => {
// Name
const setName = useCallback(
(e) => setEntry((prevEntry) => ({ ...prevEntry, name: e.target.value })),
(e: React.ChangeEvent<HTMLInputElement>) =>
setEntry((prevEntry) => ({ ...prevEntry, name: e.target.value })),
[setEntry]
);

// Sharing
const setSharingOptions = useCallback(
(value) =>
(value: string) =>
setEntry((prevEntry) => ({
...prevEntry,
users: value === i18n.SHARING_GLOBAL_OPTION_LABEL ? [] : undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
import { useCreateKnowledgeBaseEntry } from '../../assistant/api/knowledge_base/entries/use_create_knowledge_base_entry';
import { useUpdateKnowledgeBaseEntries } from '../../assistant/api/knowledge_base/entries/use_update_knowledge_base_entries';
import { SETTINGS_UPDATED_TOAST_TITLE } from '../../assistant/settings/translations';
import { KnowledgeBaseConfig } from '../../assistant/types';

export const KnowledgeBaseSettingsManagement: React.FC = React.memo(() => {
const {
Expand All @@ -68,7 +69,9 @@ export const KnowledgeBaseSettingsManagement: React.FC = React.memo(() => {
false // Knowledge Base settings do not require prompts
);

const handleUpdateKnowledgeBaseSettings = useCallback(
const handleUpdateKnowledgeBaseSettings = useCallback<
React.Dispatch<React.SetStateAction<KnowledgeBaseConfig>>
>(
(updatedKnowledgeBase) => {
setHasPendingChanges(true);
setUpdatedKnowledgeBaseSettings(updatedKnowledgeBase);
Expand Down Expand Up @@ -148,9 +151,6 @@ export const KnowledgeBaseSettingsManagement: React.FC = React.memo(() => {
setSelectedEntry(entry);
openFlyout();
},
onSpaceNameClicked: ({ namespace }: KnowledgeBaseEntryResponse) => {
openFlyout();
},
isDeleteEnabled: (entry: KnowledgeBaseEntryResponse) => {
return !isEsqlSystemEntry(entry);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ interface Props {
export const IndexEntryEditor: React.FC<Props> = React.memo(({ entry, setEntry }) => {
// Name
const setName = useCallback(
(e) => setEntry((prevEntry) => ({ ...prevEntry, name: e.target.value })),
(e: React.ChangeEvent<HTMLInputElement>) =>
setEntry((prevEntry) => ({ ...prevEntry, name: e.target.value })),
[setEntry]
);

// Sharing
const setSharingOptions = useCallback(
(value) =>
(value: string) =>
setEntry((prevEntry) => ({
...prevEntry,
users: value === i18n.SHARING_GLOBAL_OPTION_LABEL ? [] : undefined,
Expand Down Expand Up @@ -96,19 +97,22 @@ export const IndexEntryEditor: React.FC<Props> = React.memo(({ entry, setEntry }

// Field
const setField = useCallback(
(e) => setEntry((prevEntry) => ({ ...prevEntry, field: e.target.value })),
(e: React.ChangeEvent<HTMLInputElement>) =>
setEntry((prevEntry) => ({ ...prevEntry, field: e.target.value })),
[setEntry]
);

// Description
const setDescription = useCallback(
(e) => setEntry((prevEntry) => ({ ...prevEntry, description: e.target.value })),
(e: React.ChangeEvent<HTMLInputElement>) =>
setEntry((prevEntry) => ({ ...prevEntry, description: e.target.value })),
[setEntry]
);

// Query Description
const setQueryDescription = useCallback(
(e) => setEntry((prevEntry) => ({ ...prevEntry, queryDescription: e.target.value })),
(e: React.ChangeEvent<HTMLInputElement>) =>
setEntry((prevEntry) => ({ ...prevEntry, queryDescription: e.target.value })),
[setEntry]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export const useKnowledgeBaseTable = () => {
onEntryNameClicked,
onDeleteActionClicked,
onEditActionClicked,
}: {
isDeleteEnabled: (entry: KnowledgeBaseEntryResponse) => boolean;
isEditEnabled: (entry: KnowledgeBaseEntryResponse) => boolean;
onEntryNameClicked: (entry: KnowledgeBaseEntryResponse) => void;
onDeleteActionClicked: (entry: KnowledgeBaseEntryResponse) => void;
onEditActionClicked: (entry: KnowledgeBaseEntryResponse) => void;
}): Array<EuiBasicTableColumn<KnowledgeBaseEntryResponse>> => {
return [
{
Expand All @@ -55,8 +61,8 @@ export const useKnowledgeBaseTable = () => {
},
{
name: i18n.COLUMN_NAME,
render: ({ id, name }: KnowledgeBaseEntryResponse) => (
<EuiLink onClick={() => onEntryNameClicked({ id })}>{name}</EuiLink>
render: (entry: KnowledgeBaseEntryResponse) => (
<EuiLink onClick={() => onEntryNameClicked(entry)}>{entry.name}</EuiLink>
),
sortable: ({ name }: KnowledgeBaseEntryResponse) => name,
width: '30%',
Expand Down
Loading

0 comments on commit bdd57b6

Please sign in to comment.