mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
[embeddable] cleanup usages of useBatchedOptionalPublishingSubjects (#216714)
`useBatchedOptionalPublishingSubjects` should only be used when `api` is not available until after rendering. This PR replaces usages of `useBatchedOptionalPublishingSubjects` with `useBatchedPublishingSubjects` where possible. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
670ff4ee06
commit
e269d04ee0
8 changed files with 84 additions and 55 deletions
|
@ -22,51 +22,80 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { TimeRange } from '@kbn/es-query';
|
||||
import { useBatchedOptionalPublishingSubjects } from '@kbn/presentation-publishing';
|
||||
import { PublishesDataLoading, useStateFromPublishingSubject } from '@kbn/presentation-publishing';
|
||||
import { SearchEmbeddableRenderer } from '../react_embeddables/search/search_embeddable_renderer';
|
||||
import { SEARCH_EMBEDDABLE_TYPE } from '../react_embeddables/search/constants';
|
||||
import type { SearchApi, SearchSerializedState } from '../react_embeddables/search/types';
|
||||
|
||||
function DatePicker({
|
||||
dataLoading$,
|
||||
onReload,
|
||||
timeRange,
|
||||
setTimeRange,
|
||||
}: {
|
||||
dataLoading$: PublishesDataLoading['dataLoading$'];
|
||||
timeRange: TimeRange;
|
||||
setTimeRange: (timeRange: TimeRange) => void;
|
||||
onReload: () => void;
|
||||
}) {
|
||||
const dataLoading = useStateFromPublishingSubject(dataLoading$);
|
||||
return (
|
||||
<EuiSuperDatePicker
|
||||
isLoading={dataLoading ?? false}
|
||||
start={timeRange.from}
|
||||
end={timeRange.to}
|
||||
onTimeChange={({ start, end }: OnTimeChangeProps) => {
|
||||
setTimeRange({
|
||||
from: start,
|
||||
to: end,
|
||||
});
|
||||
}}
|
||||
onRefresh={() => {
|
||||
onReload();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const RenderExamples = () => {
|
||||
const parentApi = useMemo(() => {
|
||||
const timeRange$ = new BehaviorSubject<TimeRange>({
|
||||
from: 'now-24h',
|
||||
to: 'now',
|
||||
});
|
||||
const reload$ = new Subject<void>();
|
||||
return {
|
||||
reload$: new Subject<void>(),
|
||||
reload$,
|
||||
onReload: () => {
|
||||
reload$.next();
|
||||
},
|
||||
getSerializedStateForChild: () => ({
|
||||
rawState: {
|
||||
timeRange: undefined,
|
||||
},
|
||||
}),
|
||||
timeRange$: new BehaviorSubject<TimeRange>({
|
||||
from: 'now-24h',
|
||||
to: 'now',
|
||||
}),
|
||||
timeRange$,
|
||||
setTimeRange: (timeRange: TimeRange | undefined) => {
|
||||
if (timeRange) timeRange$.next(timeRange);
|
||||
},
|
||||
};
|
||||
// only run onMount
|
||||
}, []);
|
||||
|
||||
const [api, setApi] = useState<SearchApi | null>(null);
|
||||
const [hidePanelChrome, setHidePanelChrome] = useState<boolean>(false);
|
||||
const [dataLoading, timeRange] = useBatchedOptionalPublishingSubjects(
|
||||
api?.dataLoading$,
|
||||
parentApi.timeRange$
|
||||
);
|
||||
const timeRange = useStateFromPublishingSubject(parentApi.timeRange$);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<EuiSuperDatePicker
|
||||
isLoading={dataLoading ? dataLoading : false}
|
||||
start={timeRange.from}
|
||||
end={timeRange.to}
|
||||
onTimeChange={({ start, end }: OnTimeChangeProps) => {
|
||||
parentApi.timeRange$.next({
|
||||
from: start,
|
||||
to: end,
|
||||
});
|
||||
}}
|
||||
onRefresh={() => {
|
||||
parentApi.reload$.next();
|
||||
}}
|
||||
/>
|
||||
{api && (
|
||||
<DatePicker
|
||||
dataLoading$={api.dataLoading$}
|
||||
onReload={parentApi.onReload}
|
||||
setTimeRange={parentApi.setTimeRange}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
)}
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { combineLatest, debounceTime, skip } from 'rxjs';
|
||||
import { AnyPublishingSubject, PublishingSubject, UnwrapPublishingSubjectTuple } from './types';
|
||||
|
||||
|
@ -25,6 +25,8 @@ const hasSubjectsArrayChanged = (
|
|||
};
|
||||
|
||||
/**
|
||||
* @deprecated use useBatchedPublishingSubjects instead.
|
||||
*
|
||||
* Batches the latest values of multiple publishing subjects into a single object. Use this to avoid unnecessary re-renders.
|
||||
* Use when `subjects` may not be defined on initial component render.
|
||||
*
|
||||
|
@ -59,7 +61,7 @@ export const useBatchedOptionalPublishingSubjects = <
|
|||
/**
|
||||
* Subscribe to all subjects and update the latest values when any of them change.
|
||||
*/
|
||||
useEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
if (!isFirstRender.current) {
|
||||
setLatestPublishedValues(unwrapPublishingSubjectArray(subjectsToUse));
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
SerializedTitles,
|
||||
initializeTitleManager,
|
||||
SerializedPanelState,
|
||||
useBatchedOptionalPublishingSubjects,
|
||||
useBatchedPublishingSubjects,
|
||||
initializeStateManager,
|
||||
titleComparators,
|
||||
} from '@kbn/presentation-publishing';
|
||||
|
@ -257,7 +257,7 @@ export const getLinksEmbeddableFactory = () => {
|
|||
});
|
||||
|
||||
const Component = () => {
|
||||
const [links, layout] = useBatchedOptionalPublishingSubjects(
|
||||
const [links, layout] = useBatchedPublishingSubjects(
|
||||
stateManager.api.links$,
|
||||
stateManager.api.layout$
|
||||
);
|
||||
|
|
|
@ -49,10 +49,10 @@ export const PresentationPanelInternal = <
|
|||
|
||||
const dragHandles = useRef<{ [dragHandleKey: string]: HTMLElement | null }>({});
|
||||
|
||||
const viewModeSubject = (() => {
|
||||
const viewModeSubject = useMemo(() => {
|
||||
if (apiPublishesViewMode(api)) return api.viewMode$;
|
||||
if (apiHasParentApi(api) && apiPublishesViewMode(api.parentApi)) return api.parentApi.viewMode$;
|
||||
})();
|
||||
}, [api]);
|
||||
|
||||
const [
|
||||
dataLoading,
|
||||
|
|
|
@ -20,11 +20,9 @@ import {
|
|||
EuiToolTip,
|
||||
htmlIdGenerator,
|
||||
} from '@elastic/eui';
|
||||
import {
|
||||
useBatchedOptionalPublishingSubjects,
|
||||
useBatchedPublishingSubjects,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { isCompressed } from '../../../../control_group/utils/is_compressed';
|
||||
import { OptionsListSelection } from '../../../../../common/options_list/options_list_selections';
|
||||
import { MIN_POPOVER_WIDTH } from '../../../constants';
|
||||
|
@ -52,6 +50,7 @@ export const OptionsListControl = ({
|
|||
loading,
|
||||
panelTitle,
|
||||
fieldFormatter,
|
||||
defaultPanelTitle,
|
||||
] = useBatchedPublishingSubjects(
|
||||
stateManager.exclude,
|
||||
stateManager.existsSelected,
|
||||
|
@ -60,11 +59,10 @@ export const OptionsListControl = ({
|
|||
api.field$,
|
||||
api.dataLoading$,
|
||||
api.title$,
|
||||
api.fieldFormatter
|
||||
api.fieldFormatter,
|
||||
api.defaultTitle$ ?? new BehaviorSubject(undefined)
|
||||
);
|
||||
|
||||
const [defaultPanelTitle] = useBatchedOptionalPublishingSubjects(api.defaultTitle$);
|
||||
|
||||
const delimiter = useMemo(() => OptionsListStrings.control.getSeparator(field?.type), [field]);
|
||||
|
||||
const { hasSelections, selectionDisplayNode, selectedOptionsCount } = useMemo(() => {
|
||||
|
|
|
@ -29,10 +29,11 @@ import {
|
|||
EmbeddableApiContext,
|
||||
apiCanLockHoverActions,
|
||||
getViewModeSubject,
|
||||
useBatchedOptionalPublishingSubjects,
|
||||
useBatchedPublishingSubjects,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { ActionExecutionMeta } from '@kbn/ui-actions-plugin/public';
|
||||
import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { uiActionsService } from '../services/kibana_services';
|
||||
import { dashboardFilterNotificationActionStrings } from './_dashboard_actions_strings';
|
||||
import { FiltersNotificationActionApi } from './filters_notification_action';
|
||||
|
@ -77,9 +78,9 @@ export function FiltersNotificationPopover({ api }: { api: FiltersNotificationAc
|
|||
}
|
||||
}, [api, setDisableEditButton]);
|
||||
|
||||
const [dataViews, parentViewMode] = useBatchedOptionalPublishingSubjects(
|
||||
api.parentApi?.dataViews$,
|
||||
getViewModeSubject(api ?? undefined)
|
||||
const [dataViews, parentViewMode] = useBatchedPublishingSubjects(
|
||||
api.parentApi?.dataViews$ ?? new BehaviorSubject(undefined),
|
||||
getViewModeSubject(api) ?? new BehaviorSubject(undefined)
|
||||
);
|
||||
|
||||
const showEditButton = !disableEditbutton && parentViewMode === 'edit' && canEditUnifiedSearch;
|
||||
|
|
|
@ -13,10 +13,7 @@ import type { BehaviorSubject } from 'rxjs';
|
|||
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { DOC_HIDE_TIME_COLUMN_SETTING, SORT_DEFAULT_ORDER_SETTING } from '@kbn/discover-utils';
|
||||
import type { FetchContext } from '@kbn/presentation-publishing';
|
||||
import {
|
||||
useBatchedOptionalPublishingSubjects,
|
||||
useBatchedPublishingSubjects,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
|
||||
import type { SortOrder } from '@kbn/saved-search-plugin/public';
|
||||
import type { SearchResponseIncompleteWarning } from '@kbn/search-response-warnings/src/types';
|
||||
import type { DataGridDensity } from '@kbn/unified-data-table';
|
||||
|
@ -70,6 +67,10 @@ export function SearchEmbeddableGridComponent({
|
|||
totalHitCount,
|
||||
columnsMeta,
|
||||
grid,
|
||||
panelTitle,
|
||||
panelDescription,
|
||||
savedSearchTitle,
|
||||
savedSearchDescription,
|
||||
] = useBatchedPublishingSubjects(
|
||||
api.dataLoading$,
|
||||
api.savedSearch$,
|
||||
|
@ -81,7 +82,11 @@ export function SearchEmbeddableGridComponent({
|
|||
stateManager.rows,
|
||||
stateManager.totalHitCount,
|
||||
stateManager.columnsMeta,
|
||||
stateManager.grid
|
||||
stateManager.grid,
|
||||
api.title$,
|
||||
api.description$,
|
||||
api.defaultTitle$,
|
||||
api.defaultDescription$
|
||||
);
|
||||
|
||||
// `api.query$` and `api.filters$` are the initial values from the saved search SO (as of now)
|
||||
|
@ -90,14 +95,6 @@ export function SearchEmbeddableGridComponent({
|
|||
const savedSearchQuery = apiQuery;
|
||||
const savedSearchFilters = apiFilters;
|
||||
|
||||
const [panelTitle, panelDescription, savedSearchTitle, savedSearchDescription] =
|
||||
useBatchedOptionalPublishingSubjects(
|
||||
api.title$,
|
||||
api.description$,
|
||||
api.defaultTitle$,
|
||||
api.defaultDescription$
|
||||
);
|
||||
|
||||
const isEsql = useMemo(() => isEsqlMode(savedSearch), [savedSearch]);
|
||||
|
||||
const sort = useMemo(() => {
|
||||
|
|
|
@ -17,6 +17,7 @@ import type {
|
|||
HasSupportedTriggers,
|
||||
PublishesBlockingError,
|
||||
PublishesDataLoading,
|
||||
PublishesDescription,
|
||||
PublishesSavedObjectId,
|
||||
PublishesWritableTitle,
|
||||
PublishesWritableUnifiedSearch,
|
||||
|
@ -102,7 +103,8 @@ export type SearchEmbeddableApi = DefaultEmbeddableApi<SearchEmbeddableSerialize
|
|||
PublishesSavedObjectId &
|
||||
PublishesDataLoading &
|
||||
PublishesBlockingError &
|
||||
PublishesWritableTitle &
|
||||
Required<PublishesWritableTitle> &
|
||||
Required<PublishesDescription> &
|
||||
PublishesSavedSearch &
|
||||
PublishesWritableDataViews &
|
||||
PublishesWritableUnifiedSearch &
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue