mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Move useAbortController and useAbortableAsync hook into central package (#211295)
The useAbortController and useAbortableAsync hooks are very generic hooks that are useful beyond observability. This PR moves them into `react-hooks` which already houses other similar hooks. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
519d1c2b5d
commit
bc3f77238d
26 changed files with 347 additions and 27 deletions
|
@ -42,3 +42,30 @@ function App() {
|
|||
);
|
||||
}
|
||||
```
|
||||
|
||||
### [useAbortableAsync](./src/use_abortable_async/use_abortable_async.ts)
|
||||
|
||||
Wrapper around async function which is called on dependency change and can be aborted via abort controller.
|
||||
|
||||
```tsx
|
||||
const { error, loading, value, refresh } = useAbortableAsync(
|
||||
({ signal }) => {
|
||||
return fetch(url, { signal })
|
||||
},
|
||||
[url],
|
||||
{ onError: myErrorHandler }
|
||||
);
|
||||
```
|
||||
|
||||
### [useAbortController](./src/use_abort_controller/use_abort_controller.ts)
|
||||
|
||||
Hook managing an abort controller instance that aborts when it goes out of scope.
|
||||
|
||||
```tsx
|
||||
const { signal, abort, refresh } = useAbortController();
|
||||
|
||||
// ...
|
||||
|
||||
// Will be aborted when the component unmounts
|
||||
await fetch(url, { signal })
|
||||
```
|
|
@ -9,4 +9,7 @@
|
|||
|
||||
export { useBoolean } from './src/use_boolean';
|
||||
export { useErrorTextStyle } from './src/use_error_text_style';
|
||||
export { useAbortController } from './src/use_abort_controller';
|
||||
export { useAbortableAsync } from './src/use_abortable_async';
|
||||
export type { UseAbortableAsync, AbortableAsyncState } from './src/use_abortable_async';
|
||||
export type { UseBooleanHandlers, UseBooleanResult } from './src/use_boolean';
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export * from './use_abort_controller';
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* 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 { renderHook, act } from '@testing-library/react';
|
||||
import { useAbortController } from './use_abort_controller';
|
||||
|
||||
describe('useAbortController', () => {
|
||||
it('should return a valid signal and abort function', () => {
|
||||
const { result } = renderHook(() => useAbortController());
|
||||
|
||||
// Verify initial state
|
||||
expect(result.current.signal).toBeDefined();
|
||||
expect(result.current.signal.aborted).toBe(false);
|
||||
|
||||
// Call abort and test if signal becomes aborted
|
||||
act(() => {
|
||||
result.current.abort();
|
||||
});
|
||||
expect(result.current.signal.aborted).toBe(true);
|
||||
});
|
||||
|
||||
it('should refresh with a new AbortController after calling refresh', () => {
|
||||
const { result } = renderHook(() => useAbortController());
|
||||
|
||||
// Capture initial signal
|
||||
const initialSignal = result.current.signal;
|
||||
|
||||
// Abort the initial controller
|
||||
act(() => {
|
||||
result.current.abort();
|
||||
});
|
||||
expect(initialSignal.aborted).toBe(true);
|
||||
|
||||
// Refresh to get a new controller
|
||||
act(() => {
|
||||
result.current.refresh();
|
||||
});
|
||||
// The new controller should not be aborted
|
||||
expect(result.current.signal.aborted).toBe(false);
|
||||
expect(result.current.signal).not.toBe(initialSignal);
|
||||
});
|
||||
|
||||
it('should abort when the component is unmounted', () => {
|
||||
const { result, unmount } = renderHook(() => useAbortController());
|
||||
// Capture the initial signal before unmounting
|
||||
const initialSignal = result.current.signal;
|
||||
unmount();
|
||||
expect(initialSignal.aborted).toBe(true);
|
||||
});
|
||||
});
|
|
@ -1,8 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* 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 { useEffect, useState } from 'react';
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export * from './use_abortable_async';
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* 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, { useEffect } from 'react';
|
||||
import { render, act, waitFor } from '@testing-library/react';
|
||||
import { useAbortableAsync } from './use_abortable_async';
|
||||
|
||||
// Helper component to expose hook state.
|
||||
function TestComponent<T>({
|
||||
hookFn,
|
||||
onState,
|
||||
deps = [],
|
||||
}: {
|
||||
hookFn: ({ signal }: { signal: AbortSignal }) => T | Promise<T>;
|
||||
onState: (state: ReturnType<typeof useAbortableAsync>) => void;
|
||||
deps?: any[];
|
||||
}) {
|
||||
const state = useAbortableAsync(hookFn, deps);
|
||||
useEffect(() => {
|
||||
onState(state);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [state, ...deps]);
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('useAbortableAsync', () => {
|
||||
it('should handle synchronous function', async () => {
|
||||
let hookState: any;
|
||||
render(
|
||||
<TestComponent
|
||||
hookFn={() => 42}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
await waitFor(() => expect(hookState).toBeDefined());
|
||||
expect(hookState.value).toBe(42);
|
||||
expect(hookState.loading).toBe(false);
|
||||
expect(hookState.error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle asynchronous success', async () => {
|
||||
let hookState: any;
|
||||
const asyncFn = ({ signal }: { signal: AbortSignal }) =>
|
||||
new Promise<string>((resolve) => {
|
||||
const id = setTimeout(() => resolve('async result'), 10);
|
||||
// clean up
|
||||
signal.addEventListener('abort', () => clearTimeout(id));
|
||||
});
|
||||
|
||||
render(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
// Initially loading should be true.
|
||||
await waitFor(() => expect(hookState.loading).toBe(true));
|
||||
// After async completes.
|
||||
await waitFor(() => expect(hookState.loading).toBeFalsy());
|
||||
expect(hookState.error).toBeUndefined();
|
||||
expect(hookState.value).toBe('async result');
|
||||
});
|
||||
|
||||
it('should handle asynchronous error', async () => {
|
||||
let hookState: any;
|
||||
const errorFn = ({ signal }: { signal: AbortSignal }) =>
|
||||
new Promise<string>((_resolve, reject) => {
|
||||
const id = setTimeout(() => reject(new Error('fail')), 10);
|
||||
// clean up
|
||||
signal.addEventListener('abort', () => clearTimeout(id));
|
||||
});
|
||||
|
||||
render(
|
||||
<TestComponent
|
||||
hookFn={errorFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => expect(hookState.loading).toBeFalsy());
|
||||
expect(hookState.error).toBeInstanceOf(Error);
|
||||
expect(hookState.error?.message).toBe('fail');
|
||||
expect(hookState.value).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should refresh and re-run the async function', async () => {
|
||||
let hookState: any;
|
||||
let counter = 0;
|
||||
const asyncFn = ({ signal }: { signal: AbortSignal }) =>
|
||||
new Promise<number>((resolve) => {
|
||||
const id = setTimeout(() => resolve(++counter), 10);
|
||||
signal.addEventListener('abort', () => clearTimeout(id));
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => expect(hookState.loading).toBeFalsy());
|
||||
expect(hookState.value).toBe(1);
|
||||
|
||||
act(() => {
|
||||
hookState.refresh();
|
||||
});
|
||||
|
||||
// rerender to trigger update.
|
||||
rerender(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => expect(hookState.loading).toBeFalsy());
|
||||
expect(hookState.value).toBe(2);
|
||||
});
|
||||
|
||||
it('should abort previous async function when dependencies update', async () => {
|
||||
let hookState: any;
|
||||
let aborted = false;
|
||||
const asyncFn = ({ signal }: { signal: AbortSignal }) =>
|
||||
new Promise<string>(() => {
|
||||
signal.addEventListener('abort', () => {
|
||||
aborted = true;
|
||||
});
|
||||
// simulate a long running async process that never resolves
|
||||
});
|
||||
const { rerender } = render(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
deps={[1]}
|
||||
/>
|
||||
);
|
||||
// Ensure the initial async call is in-flight.
|
||||
await waitFor(() => expect(hookState.loading).toBe(true));
|
||||
// Updating the dependency should trigger abort on the previous async call.
|
||||
rerender(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
deps={[2]}
|
||||
/>
|
||||
);
|
||||
await waitFor(() => expect(aborted).toBe(true));
|
||||
});
|
||||
|
||||
it('should not abort running promise when rerendered without dependency change', async () => {
|
||||
let hookState: any;
|
||||
let aborted = false;
|
||||
const asyncFn = ({ signal }: { signal: AbortSignal }) =>
|
||||
new Promise<string>(() => {
|
||||
signal.addEventListener('abort', () => {
|
||||
aborted = true;
|
||||
});
|
||||
// simulate a long running async process that never resolves
|
||||
});
|
||||
const { rerender } = render(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
deps={[1]}
|
||||
/>
|
||||
);
|
||||
await waitFor(() => expect(hookState.loading).toBe(true));
|
||||
// Rerender with the same dependency.
|
||||
rerender(
|
||||
<TestComponent
|
||||
hookFn={asyncFn}
|
||||
onState={(state) => {
|
||||
hookState = state;
|
||||
}}
|
||||
deps={[1]} // same dependency
|
||||
/>
|
||||
);
|
||||
// Wait briefly to see if abort gets called.
|
||||
await new Promise((resolve) => setTimeout(resolve, 20));
|
||||
expect(aborted).toBe(false);
|
||||
expect(hookState.loading).toBe(true);
|
||||
});
|
||||
});
|
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* or more contributor license agreements. Licensed under the "Elastic License
|
||||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* 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 { isPromise } from '@kbn/std';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
|
@ -15,5 +15,7 @@
|
|||
"exclude": [
|
||||
"target/**/*"
|
||||
],
|
||||
"kbn_references": []
|
||||
"kbn_references": [
|
||||
"@kbn/std",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -18,6 +18,5 @@
|
|||
"kbn_references": [
|
||||
"@kbn/data-plugin",
|
||||
"@kbn/core-ui-settings-browser",
|
||||
"@kbn/std",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useAbortableAsync } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import { useAbortableAsync } from '@kbn/react-hooks';
|
||||
import { useKibana } from './use_kibana';
|
||||
|
||||
export const useFetchEntityDefinition = (id: string) => {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { useAbortableAsync } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser';
|
||||
import { useAbortableAsync } from '@kbn/react-hooks';
|
||||
import { useKibana } from './use_kibana';
|
||||
|
||||
const getDetailsFromErrorResponse = (error: IHttpFetchError<ResponseErrorBody>) =>
|
||||
|
|
|
@ -51,12 +51,10 @@
|
|||
"@kbn/rule-data-utils",
|
||||
"@kbn/spaces-plugin",
|
||||
"@kbn/cloud-plugin",
|
||||
"@kbn/observability-utils-browser",
|
||||
"@kbn/storybook",
|
||||
"@kbn/dashboard-plugin",
|
||||
"@kbn/deeplinks-analytics",
|
||||
"@kbn/react-hooks",
|
||||
"@kbn/observability-utils-browser",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/dataset-quality-plugin",
|
||||
"@kbn/observability-utils-common",
|
||||
|
|
|
@ -10,8 +10,8 @@ import type { ESQLSearchResponse } from '@kbn/es-types';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { type GlobalWidgetParameters } from '@kbn/investigate-plugin/public';
|
||||
import type { Suggestion } from '@kbn/lens-plugin/public';
|
||||
import { useAbortableAsync } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useAbortableAsync } from '@kbn/react-hooks';
|
||||
import { ErrorMessage } from '../../components/error_message';
|
||||
import { useKibana } from '../../hooks/use_kibana';
|
||||
import { getDatatableFromEsqlResponse } from '../../utils/get_data_table_from_esql_response';
|
||||
|
|
|
@ -11,8 +11,8 @@ import type { ESQLColumn, ESQLRow } from '@kbn/es-types';
|
|||
import { GlobalWidgetParameters } from '@kbn/investigate-plugin/public';
|
||||
import { Item } from '@kbn/investigation-shared';
|
||||
import type { Suggestion } from '@kbn/lens-plugin/public';
|
||||
import { useAbortableAsync } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useAbortableAsync } from '@kbn/react-hooks';
|
||||
import { ErrorMessage } from '../../../../components/error_message';
|
||||
import { SuggestVisualizationList } from '../../../../components/suggest_visualization_list';
|
||||
import { useKibana } from '../../../../hooks/use_kibana';
|
||||
|
|
|
@ -86,5 +86,6 @@
|
|||
"@kbn/dev-cli-runner",
|
||||
"@kbn/datemath",
|
||||
"@kbn/sse-utils-client",
|
||||
"@kbn/react-hooks",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
|
@ -22,7 +22,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { getTimeZone } from '@kbn/observability-utils-browser/utils/ui_settings/get_timezone';
|
||||
import { css } from '@emotion/css';
|
||||
import { AbortableAsyncState } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import { AbortableAsyncState } from '@kbn/react-hooks';
|
||||
import type { UnparsedEsqlResponse } from '@kbn/observability-utils-server/es/client/create_observability_es_client';
|
||||
import { esqlResultToTimeseries } from '../../util/esql_result_to_timeseries';
|
||||
import { useKibana } from '../../hooks/use_kibana';
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import {
|
||||
NamedFieldDefinitionConfig,
|
||||
WiredStreamGetResponse,
|
||||
|
@ -14,6 +13,7 @@ import {
|
|||
} from '@kbn/streams-schema';
|
||||
import { isEqual, omit } from 'lodash';
|
||||
import { useMemo, useCallback } from 'react';
|
||||
import { useAbortController } from '@kbn/react-hooks';
|
||||
import { useStreamsAppFetch } from '../../../hooks/use_streams_app_fetch';
|
||||
import { useKibana } from '../../../hooks/use_kibana';
|
||||
import { SchemaField, isSchemaFieldTyped } from '../types';
|
||||
|
|
|
@ -19,9 +19,9 @@ import {
|
|||
useGeneratedHtmlId,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import React from 'react';
|
||||
import { isDescendantOf } from '@kbn/streams-schema';
|
||||
import { useAbortController } from '@kbn/react-hooks';
|
||||
import { useKibana } from '../../hooks/use_kibana';
|
||||
import { useStreamsAppRouter } from '../../hooks/use_streams_app_router';
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import { useBoolean } from '@kbn/react-hooks';
|
||||
import { useAbortController, useBoolean } from '@kbn/react-hooks';
|
||||
import {
|
||||
IngestStreamGetResponse,
|
||||
isWiredStreamGetResponse,
|
||||
|
|
|
@ -21,8 +21,8 @@ import {
|
|||
IlmLocatorParams,
|
||||
PolicyFromES,
|
||||
} from '@kbn/index-lifecycle-management-common-shared';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useAbortController } from '@kbn/react-hooks';
|
||||
import { useKibana } from '../../hooks/use_kibana';
|
||||
import { EditLifecycleModal, LifecycleEditAction } from './modal';
|
||||
import { RetentionSummary } from './summary';
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
import { EuiFlexGroup, EuiButton, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||
import { WiredStreamGetResponse, IngestUpsertRequest } from '@kbn/streams-schema';
|
||||
import React from 'react';
|
||||
import { useAbortController } from '@kbn/react-hooks';
|
||||
import { useKibana } from '../../hooks/use_kibana';
|
||||
import { useStreamsAppRouter } from '../../hooks/use_streams_app_router';
|
||||
import { emptyEqualsToAlways } from '../../util/condition';
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { useCallback } from 'react';
|
||||
import { useAbortController } from '@kbn/observability-utils-browser/hooks/use_abort_controller';
|
||||
import type { SanitizedDashboardAsset } from '@kbn/streams-plugin/server/routes/dashboards/route';
|
||||
import { useAbortController } from '@kbn/react-hooks';
|
||||
import { useKibana } from './use_kibana';
|
||||
|
||||
export const useDashboardsApi = (name?: string) => {
|
||||
|
|
|
@ -6,12 +6,9 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
UseAbortableAsync,
|
||||
useAbortableAsync,
|
||||
} from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import { omit } from 'lodash';
|
||||
import { isRequestAbortedError } from '@kbn/server-route-repository-client';
|
||||
import { UseAbortableAsync, useAbortableAsync } from '@kbn/react-hooks';
|
||||
import { useKibana } from './use_kibana';
|
||||
|
||||
export const useStreamsAppFetch: UseAbortableAsync<{}, { disableToastOnError?: boolean }> = (
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { AbortableAsyncState } from '@kbn/observability-utils-browser/hooks/use_abortable_async';
|
||||
import type { AbortableAsyncState } from '@kbn/react-hooks';
|
||||
import type { UnparsedEsqlResponse } from '@kbn/observability-utils-server/es/client/create_observability_es_client';
|
||||
import { orderBy } from 'lodash';
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue