You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ms...@apache.org on 2026/09/14 17:19:25 UTC
(superset) branch msyavuz/chore/react-19 updated: chore(deps): address React 19 upgrade review comments
This is an automated email from the ASF dual-hosted git repository.
msyavuz pushed a commit to branch msyavuz/chore/react-19
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/msyavuz/chore/react-19 by this push:
new e3e23030fbc chore(deps): address React 19 upgrade review comments
e3e23030fbc is described below
commit e3e23030fbcd6488c94571a507a6b934f9990e99
Author: Mehmet Salih Yavuz <sa...@proton.me>
AuthorDate: Mon Sep 14 20:16:43 2026 +0300
chore(deps): address React 19 upgrade review comments
- Revert no-op RefObject<any | null> / useRef<any | null> back to <any>
- Replace `as unknown as` casts in DynamicComponent and Contour with typed refs/params
- Widen Select/AsyncSelect popupRender param to drop the helper cast
- Assert with mock.calls.map + toContainEqual instead of calls.at(-1)
- Type NoAnimationDropdown cloned handlers against HTMLDivElement
- Drop the react-checkbox-tree dependabot major-version ignore: its condition
(react-refresh-webpack-plugin#940) shipped in 0.6.3, which the lockfile resolves
---
.github/dependabot.yml | 4 ----
.../superset-ui-chart-controls/src/components/ColumnOption.tsx | 2 +-
.../superset-ui-chart-controls/src/components/MetricOption.tsx | 2 +-
.../superset-ui-chart-controls/src/components/labelUtils.tsx | 6 +++---
.../superset-ui-core/src/chart/components/SuperChart.tsx | 4 ++--
.../packages/superset-ui-core/src/chart/models/ChartProps.ts | 4 ++--
.../src/components/CronPicker/CronPicker.test.tsx | 2 +-
.../packages/superset-ui-core/src/components/Dropdown/index.tsx | 4 ++--
.../superset-ui-core/src/components/Select/AsyncSelect.tsx | 7 +++++--
.../packages/superset-ui-core/src/components/Select/Select.tsx | 7 +++++--
.../packages/superset-ui-core/src/components/Select/utils.tsx | 2 +-
.../src/components/ThemedAgGridReact/ThemedAgGridReact.test.tsx | 9 ++++-----
.../plugins/preset-chart-deckgl/src/layers/Contour/Contour.tsx | 3 +--
.../components/SliceHeaderControls/ViewResultsModalTrigger.tsx | 2 +-
.../src/dashboard/components/SliceHeaderControls/index.tsx | 4 ++--
.../gridComponents/DynamicComponent/DynamicComponent.tsx | 4 +++-
.../src/dashboard/components/gridComponents/Tab/Tab.test.tsx | 8 ++++++--
.../components/nativeFilters/FilterBar/FilterControls/types.ts | 2 +-
.../dashboard/components/nativeFilters/FilterBar/Vertical.tsx | 2 +-
.../DatasourcePanel/DatasourcePanelDragOption/index.tsx | 2 +-
superset-frontend/src/filters/components/Range/types.ts | 2 +-
superset-frontend/src/filters/components/Select/types.ts | 4 ++--
22 files changed, 46 insertions(+), 40 deletions(-)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index eae6e686be3..4f4443236f4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -32,10 +32,6 @@ updates:
# `just-handlerbars-helpers` library in plugin-chart-handlebars requires `currencyformatter`` to be < 2
- dependency-name: "currencyformatter.js"
update-types: ["version-update:semver-major"]
- # TODO: remove below clause once https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/940 lands onto a future release
- # and confirm the issue https://github.com/apache/superset/issues/39600 is fixed
- - dependency-name: "react-checkbox-tree"
- update-types: ["version-update:semver-major"]
# Babel 8 (7.x -> 8.x) is blocked on the surrounding ecosystem: @emotion/babel-plugin
# (NodePath#hoist), babel-plugin-jsx-remove-data-test-id (t.jSXOpeningElement), and
# ts-jest all rely on Babel APIs removed in v8 and have not shipped Babel 8 support.
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx
index 013944196ac..17f02eecbd5 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnOption.tsx
@@ -36,7 +36,7 @@ import { SQLPopover } from './SQLPopover';
export type ColumnOptionProps = {
column: ColumnMeta;
showType?: boolean;
- labelRef?: RefObject<any | null>;
+ labelRef?: RefObject<any>;
};
const StyleOverrides = styled.span`
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx
index 2eac820cb02..8698f26f4bd 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx
@@ -47,7 +47,7 @@ export interface MetricOptionProps {
showFormula?: boolean;
showType?: boolean;
url?: string;
- labelRef?: RefObject<any | null>;
+ labelRef?: RefObject<any>;
shouldShowTooltip?: boolean;
}
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx
index 2318fb2e584..ffee313a4df 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/labelUtils.tsx
@@ -58,7 +58,7 @@ const TooltipSection = ({
</TooltipSectionWrapper>
);
-export const isLabelTruncated = (labelRef?: RefObject<any | null>): boolean =>
+export const isLabelTruncated = (labelRef?: RefObject<any>): boolean =>
!!(labelRef?.current?.scrollWidth > labelRef?.current?.clientWidth);
export const getColumnLabelText = (column: ColumnMeta): string =>
@@ -92,7 +92,7 @@ export const getColumnTypeTooltipNode = (column: ColumnMeta): ReactNode => {
export const getColumnTooltipNode = (
column: ColumnMeta,
- labelRef?: RefObject<any | null>,
+ labelRef?: RefObject<any>,
): ReactNode => {
if (
(!column.column_name || !column.verbose_name) &&
@@ -121,7 +121,7 @@ type MetricType = Omit<Metric, 'id' | 'uuid'> & { label?: string };
export const getMetricTooltipNode = (
metric: MetricType,
- labelRef?: RefObject<any | null>,
+ labelRef?: RefObject<any>,
): ReactNode => {
if (
!metric.verbose_name &&
diff --git a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
index b6942dd84d2..d917e7253c0 100644
--- a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
@@ -77,9 +77,9 @@ export type Props = Omit<SuperChartCoreProps, 'chartProps'> &
/** Prop for form plugins using superchart */
showOverflow?: boolean;
/** Prop for popovercontainer ref */
- parentRef?: RefObject<any | null>;
+ parentRef?: RefObject<any>;
/** Prop for chart ref */
- inputRef?: RefObject<any | null>;
+ inputRef?: RefObject<any>;
/** Chart width */
height?: number | string;
/** Chart height */
diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
index 4100e8a278c..99519d16e37 100644
--- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
+++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartProps.ts
@@ -130,7 +130,7 @@ export interface ChartPropsConfig {
/** is the chart refreshing its contents */
isRefreshing?: boolean;
/** chart ref */
- inputRef?: RefObject<any | null>;
+ inputRef?: RefObject<any>;
/** Theme object */
theme: SupersetTheme;
/* legend index */
@@ -181,7 +181,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
isRefreshing?: boolean;
- inputRef?: RefObject<any | null>;
+ inputRef?: RefObject<any>;
inContextMenu?: boolean;
diff --git a/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx
index 22e00667f0c..6463c810a8c 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/CronPicker/CronPicker.test.tsx
@@ -30,7 +30,7 @@ test('Should send correct props to ReactCronPicker', () => {
render(<CronPicker {...(props as any)} />);
// React 19 calls function components with a single props argument, so assert
// on the props rather than the whole call signature.
- expect(spy.mock.calls.at(-1)?.[0]).toEqual(
+ expect(spy.mock.calls.map(call => call[0])).toContainEqual(
expect.objectContaining({
className: expect.any(String),
locale: expect.anything(),
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx
index 8461d618e71..33b7f16c558 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Dropdown/index.tsx
@@ -116,8 +116,8 @@ export const NoAnimationDropdown = (props: NoAnimationDropdownProps) => {
const { children, onBlur, onKeyDown, ...rest } = props;
const childrenWithProps = cloneElement(
children as ReactElement<{
- onBlur?: FocusEventHandler;
- onKeyDown?: KeyboardEventHandler;
+ onBlur?: FocusEventHandler<HTMLDivElement>;
+ onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
}>,
{
onBlur,
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx
index a08c17189b4..123bd0fe3a7 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Select/AsyncSelect.tsx
@@ -56,6 +56,7 @@ import {
sortComparatorForNoSearchHelper,
getSuffixIcon,
dropDownRenderHelper,
+ type FlattenOptionsProps,
handleFilterOptionHelper,
makeQuoteAwareTokenizer,
mapOptions,
@@ -666,10 +667,12 @@ const AsyncSelect = forwardRef(
};
const popupRender = (
- originNode: ReactElement & { ref?: RefObject<HTMLElement> },
+ originNode: ReactElement<FlattenOptionsProps> & {
+ ref?: RefObject<HTMLElement | null>;
+ },
) =>
dropDownRenderHelper(
- originNode as Parameters<typeof dropDownRenderHelper>[0],
+ originNode,
isDropdownVisible,
isLoading,
fullSelectOptions.length,
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx
index 06147119cd9..b3fc6ed4a5a 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx
@@ -42,6 +42,7 @@ import {
import { debounce, isEqual, uniq } from 'lodash-es';
import {
dropDownRenderHelper,
+ type FlattenOptionsProps,
getOption,
getSuffixIcon,
getValue,
@@ -763,10 +764,12 @@ const Select = forwardRef(
const isLoading = loading ?? false;
const popupRender = (
- originNode: ReactElement & { ref?: RefObject<HTMLElement | null> },
+ originNode: ReactElement<FlattenOptionsProps> & {
+ ref?: RefObject<HTMLElement | null>;
+ },
) =>
dropDownRenderHelper(
- originNode as Parameters<typeof dropDownRenderHelper>[0],
+ originNode,
isDropdownVisible,
isLoading,
fullSelectOptions.length,
diff --git a/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx
index e51ddd8523a..4dd2508a1e0 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/Select/utils.tsx
@@ -165,7 +165,7 @@ export const getSuffixIcon = (
return <Icons.DownOutlined iconSize="s" aria-label="down" />;
};
-type FlattenOptionsProps = {
+export type FlattenOptionsProps = {
flattenOptions?: Array<Record<string, any>>;
};
diff --git a/superset-frontend/packages/superset-ui-core/src/components/ThemedAgGridReact/ThemedAgGridReact.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/ThemedAgGridReact/ThemedAgGridReact.test.tsx
index ab66c9d0ff6..9e226105620 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/ThemedAgGridReact/ThemedAgGridReact.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/ThemedAgGridReact/ThemedAgGridReact.test.tsx
@@ -122,9 +122,8 @@ test('applies dark theme when background is dark', () => {
expect(theme.foregroundColor).toBe('#ffffff');
});
-// The props AgGridReact was last rendered with.
-const agGridProps = () =>
- (AgGridReact as unknown as jest.Mock).mock.calls.at(-1)?.[0];
+const agGridPropsCalls = () =>
+ (AgGridReact as unknown as jest.Mock).mock.calls.map(call => call[0]);
test('forwards ref to AgGridReact', () => {
const ref = createRef<AgGridReact>();
@@ -139,7 +138,7 @@ test('forwards ref to AgGridReact', () => {
// React 19 hands `ref` to the component as a regular prop rather than as a
// second argument, so assert on the props object itself.
- expect(agGridProps()).toEqual(
+ expect(agGridPropsCalls()).toContainEqual(
expect.objectContaining({
rowData: mockRowData,
columnDefs: mockColumnDefs,
@@ -165,7 +164,7 @@ test('passes all props through to AgGridReact', () => {
// onGridReady and onFirstDataRendered are intercepted by the component to expose
// the grid API on the container element; the wrapped function is passed instead.
- expect(agGridProps()).toEqual(
+ expect(agGridPropsCalls()).toContainEqual(
expect.objectContaining({
rowData: mockRowData,
columnDefs: mockColumnDefs,
diff --git a/superset-frontend/plugins/preset-chart-deckgl/src/layers/Contour/Contour.tsx b/superset-frontend/plugins/preset-chart-deckgl/src/layers/Contour/Contour.tsx
index 9e024dddcd4..03433fc9cee 100644
--- a/superset-frontend/plugins/preset-chart-deckgl/src/layers/Contour/Contour.tsx
+++ b/superset-frontend/plugins/preset-chart-deckgl/src/layers/Contour/Contour.tsx
@@ -166,8 +166,7 @@ export const getLayer: GetLayerType<ContourLayer> = function ({
contours,
cellSize: safeCellSize,
aggregation: aggregation.toUpperCase(),
- getPosition: (d: { position: number[]; weight: number }) =>
- d.position as unknown as Position,
+ getPosition: (d: { position: Position; weight: number }) => d.position,
getWeight: (d: { weight: number }) => d.weight || 0,
...commonLayerProps({
formData: fd,
diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/ViewResultsModalTrigger.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/ViewResultsModalTrigger.tsx
index 0587c2e64f7..f1a509870d9 100644
--- a/superset-frontend/src/dashboard/components/SliceHeaderControls/ViewResultsModalTrigger.tsx
+++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/ViewResultsModalTrigger.tsx
@@ -35,7 +35,7 @@ export const ViewResultsModalTrigger = ({
triggerNode: ReactNode;
modalTitle: string;
modalBody: ReactNode;
- modalRef?: RefObject<any | null>;
+ modalRef?: RefObject<any>;
}) => {
const history = useHistory();
const exploreChart = () => history.push(exploreUrl);
diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
index 2952b8a12d8..832cb545ed1 100644
--- a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
+++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx
@@ -180,8 +180,8 @@ const SliceHeaderControls = (
);
const history = useHistory();
- const queryMenuRef: RefObject<any | null> = useRef(null);
- const resultsMenuRef: RefObject<any | null> = useRef(null);
+ const queryMenuRef: RefObject<any> = useRef(null);
+ const resultsMenuRef: RefObject<any> = useRef(null);
const [modalFilters, setFilters] = useState<BinaryQueryObjectFilterClause[]>(
[],
diff --git a/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent/DynamicComponent.tsx b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent/DynamicComponent.tsx
index 02acfce2fc4..d3232fbde4e 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent/DynamicComponent.tsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/DynamicComponent/DynamicComponent.tsx
@@ -158,7 +158,9 @@ const DynamicComponent: FC<DynamicComponentProps> = ({
onResizeStop={onResizeStop}
>
<div
- ref={dragSourceRef as unknown as React.Ref<HTMLDivElement>}
+ ref={el => {
+ dragSourceRef(el);
+ }}
className="dashboard-component"
data-test="dashboard-component-chart-holder"
>
diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tab/Tab.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/Tab/Tab.test.tsx
index b5a57c039e1..838f4b3f16f 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Tab/Tab.test.tsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Tab/Tab.test.tsx
@@ -172,7 +172,9 @@ test('passes correct canEdit and editing props to EditableTitle', () => {
useDnd: true,
});
- expect((EditableTitle as jest.Mock).mock.calls.at(-1)?.[0]).toEqual(
+ expect(
+ (EditableTitle as jest.Mock).mock.calls.map(call => call[0]),
+ ).toContainEqual(
expect.objectContaining({
title: '🚀 Aspiring Developers',
canEdit: true,
@@ -188,7 +190,9 @@ test('passes correct canEdit and editing props to EditableTitle', () => {
useDnd: true,
});
- expect((EditableTitle as jest.Mock).mock.calls.at(-1)?.[0]).toEqual(
+ expect(
+ (EditableTitle as jest.Mock).mock.calls.map(call => call[0]),
+ ).toContainEqual(
expect.objectContaining({
title: '🚀 Aspiring Developers',
canEdit: true,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
index 5c1a7468c73..e493982aba6 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/types.ts
@@ -50,7 +50,7 @@ export interface FilterControlProps extends BaseFilterProps {
onFilterSelectionChange: (filter: FilterElement, dataMask: DataMask) => void;
inView?: boolean;
showOverflow?: boolean;
- parentRef?: RefObject<any | null>;
+ parentRef?: RefObject<any>;
setFilterActive?: (isActive: boolean) => void;
validateStatus?: string;
clearAllTrigger?: boolean;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
index dbfc668157d..26df049e31a 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
@@ -149,7 +149,7 @@ const VerticalFilterBar: FC<VerticalBarProps> = ({
}) => {
const theme = useTheme();
const [isScrolling, setIsScrolling] = useState(false);
- const timeout = useRef<any | null>(null);
+ const timeout = useRef<any>(null);
const openFiltersBar = useCallback(
() => toggleFiltersBar(true),
diff --git a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx
index 1ae526c5462..2d41913f04d 100644
--- a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx
+++ b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx
@@ -60,7 +60,7 @@ const DatasourceItemContainer = styled.div<{ isDragging?: boolean }>`
`;
interface DatasourcePanelDragOptionProps extends DatasourcePanelDndItem {
- labelRef?: RefObject<any | null>;
+ labelRef?: RefObject<any>;
showTooltip?: boolean;
}
diff --git a/superset-frontend/src/filters/components/Range/types.ts b/superset-frontend/src/filters/components/Range/types.ts
index be27590ba10..d020ebf96d0 100644
--- a/superset-frontend/src/filters/components/Range/types.ts
+++ b/superset-frontend/src/filters/components/Range/types.ts
@@ -47,7 +47,7 @@ export type PluginFilterRangeProps = PluginFilterStylesProps & {
formData: PluginFilterRangeQueryFormData;
filterState: FilterState;
behaviors: Behavior[];
- inputRef: RefObject<any | null>;
+ inputRef: RefObject<any>;
filterBarOrientation?: FilterBarOrientation;
isOverflowingFilterBar?: boolean;
} & PluginFilterHooks;
diff --git a/superset-frontend/src/filters/components/Select/types.ts b/superset-frontend/src/filters/components/Select/types.ts
index 689582cbc50..2e2a81d37dd 100644
--- a/superset-frontend/src/filters/components/Select/types.ts
+++ b/superset-frontend/src/filters/components/Select/types.ts
@@ -69,8 +69,8 @@ export type PluginFilterSelectProps = PluginFilterStylesProps & {
filterState: FilterState;
isRefreshing: boolean;
showOverflow: boolean;
- parentRef?: RefObject<any | null>;
- inputRef?: RefObject<any | null>;
+ parentRef?: RefObject<any>;
+ inputRef?: RefObject<any>;
filterBarOrientation?: FilterBarOrientation;
isOverflowingFilterBar?: boolean;
clearAllTrigger?: Record<string, boolean>;