Skip to content

Commit 9a80f94

Browse files
kibanamachinenreeseelasticmachine
authored
[8.19] [embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714) (#220428)
# Backport This will backport the following commits from `main` to `8.19`: - [[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714)](#216714) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Nathan Reese","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-05-07T19:32:33Z","message":"[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714)\n\n`useBatchedOptionalPublishingSubjects` should only be used when `api` is\nnot available until after rendering. This PR replaces usages of\n`useBatchedOptionalPublishingSubjects` with\n`useBatchedPublishingSubjects` where possible.\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Elastic Machine <[email protected]>","sha":"e269d04ee097b8c56464066cad4477e04ed3daa8","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Presentation","release_note:skip","backport:version","v9.1.0","v8.19.0"],"title":"[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects","number":216714,"url":"https://github.com/elastic/kibana/pull/216714","mergeCommit":{"message":"[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714)\n\n`useBatchedOptionalPublishingSubjects` should only be used when `api` is\nnot available until after rendering. This PR replaces usages of\n`useBatchedOptionalPublishingSubjects` with\n`useBatchedPublishingSubjects` where possible.\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Elastic Machine <[email protected]>","sha":"e269d04ee097b8c56464066cad4477e04ed3daa8"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/216714","number":216714,"mergeCommit":{"message":"[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714)\n\n`useBatchedOptionalPublishingSubjects` should only be used when `api` is\nnot available until after rendering. This PR replaces usages of\n`useBatchedOptionalPublishingSubjects` with\n`useBatchedPublishingSubjects` where possible.\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Elastic Machine <[email protected]>","sha":"e269d04ee097b8c56464066cad4477e04ed3daa8"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Nathan Reese <[email protected]> Co-authored-by: Elastic Machine <[email protected]>
1 parent 2f41969 commit 9a80f94

File tree

8 files changed

+84
-55
lines changed

8 files changed

+84
-55
lines changed

examples/embeddable_examples/public/app/render_examples.tsx

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,80 @@ import {
2222
} from '@elastic/eui';
2323
import { BehaviorSubject, Subject } from 'rxjs';
2424
import { TimeRange } from '@kbn/es-query';
25-
import { useBatchedOptionalPublishingSubjects } from '@kbn/presentation-publishing';
25+
import { PublishesDataLoading, useStateFromPublishingSubject } from '@kbn/presentation-publishing';
2626
import { SearchEmbeddableRenderer } from '../react_embeddables/search/search_embeddable_renderer';
2727
import { SEARCH_EMBEDDABLE_TYPE } from '../react_embeddables/search/constants';
2828
import type { SearchApi, SearchSerializedState } from '../react_embeddables/search/types';
2929

30+
function DatePicker({
31+
dataLoading$,
32+
onReload,
33+
timeRange,
34+
setTimeRange,
35+
}: {
36+
dataLoading$: PublishesDataLoading['dataLoading$'];
37+
timeRange: TimeRange;
38+
setTimeRange: (timeRange: TimeRange) => void;
39+
onReload: () => void;
40+
}) {
41+
const dataLoading = useStateFromPublishingSubject(dataLoading$);
42+
return (
43+
<EuiSuperDatePicker
44+
isLoading={dataLoading ?? false}
45+
start={timeRange.from}
46+
end={timeRange.to}
47+
onTimeChange={({ start, end }: OnTimeChangeProps) => {
48+
setTimeRange({
49+
from: start,
50+
to: end,
51+
});
52+
}}
53+
onRefresh={() => {
54+
onReload();
55+
}}
56+
/>
57+
);
58+
}
59+
3060
export const RenderExamples = () => {
3161
const parentApi = useMemo(() => {
62+
const timeRange$ = new BehaviorSubject<TimeRange>({
63+
from: 'now-24h',
64+
to: 'now',
65+
});
66+
const reload$ = new Subject<void>();
3267
return {
33-
reload$: new Subject<void>(),
68+
reload$,
69+
onReload: () => {
70+
reload$.next();
71+
},
3472
getSerializedStateForChild: () => ({
3573
rawState: {
3674
timeRange: undefined,
3775
},
3876
}),
39-
timeRange$: new BehaviorSubject<TimeRange>({
40-
from: 'now-24h',
41-
to: 'now',
42-
}),
77+
timeRange$,
78+
setTimeRange: (timeRange: TimeRange | undefined) => {
79+
if (timeRange) timeRange$.next(timeRange);
80+
},
4381
};
4482
// only run onMount
4583
}, []);
4684

4785
const [api, setApi] = useState<SearchApi | null>(null);
4886
const [hidePanelChrome, setHidePanelChrome] = useState<boolean>(false);
49-
const [dataLoading, timeRange] = useBatchedOptionalPublishingSubjects(
50-
api?.dataLoading$,
51-
parentApi.timeRange$
52-
);
87+
const timeRange = useStateFromPublishingSubject(parentApi.timeRange$);
5388

5489
return (
5590
<div>
56-
<EuiSuperDatePicker
57-
isLoading={dataLoading ? dataLoading : false}
58-
start={timeRange.from}
59-
end={timeRange.to}
60-
onTimeChange={({ start, end }: OnTimeChangeProps) => {
61-
parentApi.timeRange$.next({
62-
from: start,
63-
to: end,
64-
});
65-
}}
66-
onRefresh={() => {
67-
parentApi.reload$.next();
68-
}}
69-
/>
91+
{api && (
92+
<DatePicker
93+
dataLoading$={api.dataLoading$}
94+
onReload={parentApi.onReload}
95+
setTimeRange={parentApi.setTimeRange}
96+
timeRange={timeRange}
97+
/>
98+
)}
7099

71100
<EuiSpacer size="s" />
72101

src/platform/packages/shared/presentation/presentation_publishing/publishing_subject/publishing_batcher.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import { useEffect, useMemo, useRef, useState } from 'react';
10+
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
1111
import { combineLatest, debounceTime, skip } from 'rxjs';
1212
import { AnyPublishingSubject, PublishingSubject, UnwrapPublishingSubjectTuple } from './types';
1313

@@ -25,6 +25,8 @@ const hasSubjectsArrayChanged = (
2525
};
2626

2727
/**
28+
* @deprecated use useBatchedPublishingSubjects instead.
29+
*
2830
* Batches the latest values of multiple publishing subjects into a single object. Use this to avoid unnecessary re-renders.
2931
* Use when `subjects` may not be defined on initial component render.
3032
*
@@ -59,7 +61,7 @@ export const useBatchedOptionalPublishingSubjects = <
5961
/**
6062
* Subscribe to all subjects and update the latest values when any of them change.
6163
*/
62-
useEffect(() => {
64+
useLayoutEffect(() => {
6365
if (!isFirstRender.current) {
6466
setLatestPublishedValues(unwrapPublishingSubjectArray(subjectsToUse));
6567
} else {

src/platform/plugins/private/links/public/embeddable/links_embeddable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
SerializedTitles,
1919
initializeTitleManager,
2020
SerializedPanelState,
21-
useBatchedOptionalPublishingSubjects,
21+
useBatchedPublishingSubjects,
2222
initializeStateManager,
2323
titleComparators,
2424
} from '@kbn/presentation-publishing';
@@ -257,7 +257,7 @@ export const getLinksEmbeddableFactory = () => {
257257
});
258258

259259
const Component = () => {
260-
const [links, layout] = useBatchedOptionalPublishingSubjects(
260+
const [links, layout] = useBatchedPublishingSubjects(
261261
stateManager.api.links$,
262262
stateManager.api.layout$
263263
);

src/platform/plugins/private/presentation_panel/public/panel_component/presentation_panel_internal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ export const PresentationPanelInternal = <
4949

5050
const dragHandles = useRef<{ [dragHandleKey: string]: HTMLElement | null }>({});
5151

52-
const viewModeSubject = (() => {
52+
const viewModeSubject = useMemo(() => {
5353
if (apiPublishesViewMode(api)) return api.viewMode$;
5454
if (apiHasParentApi(api) && apiPublishesViewMode(api.parentApi)) return api.parentApi.viewMode$;
55-
})();
55+
}, [api]);
5656

5757
const [
5858
dataLoading,

src/platform/plugins/shared/controls/public/controls/data_controls/options_list_control/components/options_list_control.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ import {
2020
EuiToolTip,
2121
htmlIdGenerator,
2222
} from '@elastic/eui';
23-
import {
24-
useBatchedOptionalPublishingSubjects,
25-
useBatchedPublishingSubjects,
26-
} from '@kbn/presentation-publishing';
23+
import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
2724

25+
import { BehaviorSubject } from 'rxjs';
2826
import { isCompressed } from '../../../../control_group/utils/is_compressed';
2927
import { OptionsListSelection } from '../../../../../common/options_list/options_list_selections';
3028
import { MIN_POPOVER_WIDTH } from '../../../constants';
@@ -52,6 +50,7 @@ export const OptionsListControl = ({
5250
loading,
5351
panelTitle,
5452
fieldFormatter,
53+
defaultPanelTitle,
5554
] = useBatchedPublishingSubjects(
5655
stateManager.exclude,
5756
stateManager.existsSelected,
@@ -60,11 +59,10 @@ export const OptionsListControl = ({
6059
api.field$,
6160
api.dataLoading$,
6261
api.title$,
63-
api.fieldFormatter
62+
api.fieldFormatter,
63+
api.defaultTitle$ ?? new BehaviorSubject(undefined)
6464
);
6565

66-
const [defaultPanelTitle] = useBatchedOptionalPublishingSubjects(api.defaultTitle$);
67-
6866
const delimiter = useMemo(() => OptionsListStrings.control.getSeparator(field?.type), [field]);
6967

7068
const { hasSelections, selectionDisplayNode, selectedOptionsCount } = useMemo(() => {

src/platform/plugins/shared/dashboard/public/dashboard_actions/filters_notification_popover.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ import {
2929
EmbeddableApiContext,
3030
apiCanLockHoverActions,
3131
getViewModeSubject,
32-
useBatchedOptionalPublishingSubjects,
32+
useBatchedPublishingSubjects,
3333
} from '@kbn/presentation-publishing';
3434
import { ActionExecutionMeta } from '@kbn/ui-actions-plugin/public';
3535
import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
36+
import { BehaviorSubject } from 'rxjs';
3637
import { uiActionsService } from '../services/kibana_services';
3738
import { dashboardFilterNotificationActionStrings } from './_dashboard_actions_strings';
3839
import { FiltersNotificationActionApi } from './filters_notification_action';
@@ -76,9 +77,9 @@ export function FiltersNotificationPopover({ api }: { api: FiltersNotificationAc
7677
}
7778
}, [api, setDisableEditButton]);
7879

79-
const [dataViews, parentViewMode] = useBatchedOptionalPublishingSubjects(
80-
api.parentApi?.dataViews$,
81-
getViewModeSubject(api ?? undefined)
80+
const [dataViews, parentViewMode] = useBatchedPublishingSubjects(
81+
api.parentApi?.dataViews$ ?? new BehaviorSubject(undefined),
82+
getViewModeSubject(api) ?? new BehaviorSubject(undefined)
8283
);
8384

8485
return (

src/platform/plugins/shared/discover/public/embeddable/components/search_embeddable_grid_component.tsx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ import type { BehaviorSubject } from 'rxjs';
1212

1313
import type { DataView } from '@kbn/data-views-plugin/common';
1414
import type { FetchContext } from '@kbn/presentation-publishing';
15-
import {
16-
useBatchedOptionalPublishingSubjects,
17-
useBatchedPublishingSubjects,
18-
} from '@kbn/presentation-publishing';
15+
import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
1916
import type { SortOrder } from '@kbn/saved-search-plugin/public';
2017
import type { SearchResponseIncompleteWarning } from '@kbn/search-response-warnings/src/types';
2118
import type { DataGridDensity } from '@kbn/unified-data-table';
@@ -77,6 +74,10 @@ export function SearchEmbeddableGridComponent({
7774
totalHitCount,
7875
columnsMeta,
7976
grid,
77+
panelTitle,
78+
panelDescription,
79+
savedSearchTitle,
80+
savedSearchDescription,
8081
] = useBatchedPublishingSubjects(
8182
api.dataLoading$,
8283
api.savedSearch$,
@@ -88,7 +89,11 @@ export function SearchEmbeddableGridComponent({
8889
stateManager.rows,
8990
stateManager.totalHitCount,
9091
stateManager.columnsMeta,
91-
stateManager.grid
92+
stateManager.grid,
93+
api.title$,
94+
api.description$,
95+
api.defaultTitle$,
96+
api.defaultDescription$
9297
);
9398

9499
// `api.query$` and `api.filters$` are the initial values from the saved search SO (as of now)
@@ -97,14 +102,6 @@ export function SearchEmbeddableGridComponent({
97102
const savedSearchQuery = apiQuery;
98103
const savedSearchFilters = apiFilters;
99104

100-
const [panelTitle, panelDescription, savedSearchTitle, savedSearchDescription] =
101-
useBatchedOptionalPublishingSubjects(
102-
api.title$,
103-
api.description$,
104-
api.defaultTitle$,
105-
api.defaultDescription$
106-
);
107-
108105
const isEsql = useMemo(() => isEsqlMode(savedSearch), [savedSearch]);
109106
const useLegacyTable = useMemo(
110107
() =>

src/platform/plugins/shared/discover/public/embeddable/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
HasSupportedTriggers,
1818
PublishesBlockingError,
1919
PublishesDataLoading,
20+
PublishesDescription,
2021
PublishesSavedObjectId,
2122
PublishesWritableTitle,
2223
PublishesWritableUnifiedSearch,
@@ -102,7 +103,8 @@ export type SearchEmbeddableApi = DefaultEmbeddableApi<SearchEmbeddableSerialize
102103
PublishesSavedObjectId &
103104
PublishesDataLoading &
104105
PublishesBlockingError &
105-
PublishesWritableTitle &
106+
Required<PublishesWritableTitle> &
107+
Required<PublishesDescription> &
106108
PublishesSavedSearch &
107109
PublishesWritableDataViews &
108110
PublishesWritableUnifiedSearch &

0 commit comments

Comments
 (0)