diff --git a/public/app/features/dashboard/dashgrid/LazyLoader.tsx b/public/app/features/dashboard/dashgrid/LazyLoader.tsx index 6bf02bf7bf4..e42d4c8f9c9 100644 --- a/public/app/features/dashboard/dashgrid/LazyLoader.tsx +++ b/public/app/features/dashboard/dashgrid/LazyLoader.tsx @@ -1,8 +1,6 @@ -import React, { useRef, useState } from 'react'; +import React, { useId, useRef, useState } from 'react'; import { useEffectOnce } from 'react-use'; -import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId'; - export interface Props { children: React.ReactNode | (({ isInView }: { isInView: boolean }) => React.ReactNode); width?: number; @@ -12,7 +10,7 @@ export interface Props { } export function LazyLoader({ children, width, height, onLoad, onChange }: Props) { - const id = useUniqueId(); + const id = useId(); const [loaded, setLoaded] = useState(false); const [isInView, setIsInView] = useState(false); const wrapperRef = useRef(null); diff --git a/public/app/features/search/page/components/FolderSection.tsx b/public/app/features/search/page/components/FolderSection.tsx index 0ce2aa52046..4028ac70fc9 100644 --- a/public/app/features/search/page/components/FolderSection.tsx +++ b/public/app/features/search/page/components/FolderSection.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React, { useCallback } from 'react'; +import React, { useCallback, useId } from 'react'; import { useAsync, useLocalStorage } from 'react-use'; import { GrafanaTheme2, toIconName } from '@grafana/data'; @@ -8,7 +8,6 @@ import { Card, Checkbox, CollapsableSection, Icon, Spinner, useStyles2 } from '@ import { config } from 'app/core/config'; import { t } from 'app/core/internationalization'; import { getSectionStorageKey } from 'app/features/search/utils'; -import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId'; import { SearchItem } from '../..'; import { GENERAL_FOLDER_UID } from '../../constants'; @@ -91,7 +90,7 @@ export const FolderSection = ({ } }; - const id = useUniqueId(); + const id = useId(); const labelId = `section-header-label-${id}`; let icon = toIconName(section.icon ?? ''); diff --git a/public/app/features/variables/editor/VariableSelectField.tsx b/public/app/features/variables/editor/VariableSelectField.tsx index ef7bb998369..d1cc5bf017b 100644 --- a/public/app/features/variables/editor/VariableSelectField.tsx +++ b/public/app/features/variables/editor/VariableSelectField.tsx @@ -1,9 +1,8 @@ import { css } from '@emotion/css'; -import React, { PropsWithChildren, ReactElement } from 'react'; +import React, { PropsWithChildren, ReactElement, useId } from 'react'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { Field, Select, useStyles2 } from '@grafana/ui'; -import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId'; interface VariableSelectFieldProps { name: string; @@ -25,7 +24,7 @@ export function VariableSelectField({ width, }: PropsWithChildren>): ReactElement { const styles = useStyles2(getStyles); - const uniqueId = useUniqueId(); + const uniqueId = useId(); const inputId = `variable-select-input-${name}-${uniqueId}`; return ( diff --git a/public/app/plugins/datasource/influxdb/components/RawInfluxQLEditor.tsx b/public/app/plugins/datasource/influxdb/components/RawInfluxQLEditor.tsx index 8bf1d787b4e..22b82dcc653 100644 --- a/public/app/plugins/datasource/influxdb/components/RawInfluxQLEditor.tsx +++ b/public/app/plugins/datasource/influxdb/components/RawInfluxQLEditor.tsx @@ -1,12 +1,11 @@ -import React from 'react'; +import React, { useId } from 'react'; -import { TextArea, InlineFormLabel, Input, Select, HorizontalGroup } from '@grafana/ui'; +import { HorizontalGroup, InlineFormLabel, Input, Select, TextArea } from '@grafana/ui'; import { InfluxQuery } from '../types'; -import { RESULT_FORMATS, DEFAULT_RESULT_FORMAT } from './constants'; +import { DEFAULT_RESULT_FORMAT, RESULT_FORMATS } from './constants'; import { useShadowedState } from './useShadowedState'; -import { useUniqueId } from './useUniqueId'; type Props = { query: InfluxQuery; @@ -20,8 +19,8 @@ type Props = { export const RawInfluxQLEditor = ({ query, onChange, onRunQuery }: Props): JSX.Element => { const [currentQuery, setCurrentQuery] = useShadowedState(query.query); const [currentAlias, setCurrentAlias] = useShadowedState(query.alias); - const aliasElementId = useUniqueId(); - const selectElementId = useUniqueId(); + const aliasElementId = useId(); + const selectElementId = useId(); const resultFormat = query.resultFormat ?? DEFAULT_RESULT_FORMAT; diff --git a/public/app/plugins/datasource/influxdb/components/VisualInfluxQLEditor/Editor.tsx b/public/app/plugins/datasource/influxdb/components/VisualInfluxQLEditor/Editor.tsx index 27477576254..9e69be2ab5a 100644 --- a/public/app/plugins/datasource/influxdb/components/VisualInfluxQLEditor/Editor.tsx +++ b/public/app/plugins/datasource/influxdb/components/VisualInfluxQLEditor/Editor.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React, { useMemo } from 'react'; +import React, { useId, useMemo } from 'react'; import { useAsync } from 'react-use'; import { GrafanaTheme2, TypedVariableModel } from '@grafana/data'; @@ -25,7 +25,6 @@ import { } from '../../queryUtils'; import { InfluxQuery, InfluxQueryTag } from '../../types'; import { DEFAULT_RESULT_FORMAT } from '../constants'; -import { useUniqueId } from '../useUniqueId'; import { FormatAsSection } from './FormatAsSection'; import { FromSection } from './FromSection'; @@ -80,7 +79,7 @@ function filterTags(parts: InfluxQueryTag[], allTagKeys: Set): InfluxQue } export const Editor = (props: Props): JSX.Element => { - const uniqueId = useUniqueId(); + const uniqueId = useId(); const formatAsId = `influxdb-qe-format-as-${uniqueId}`; const orderByTimeId = `influxdb-qe-order-by${uniqueId}`; diff --git a/public/app/plugins/datasource/influxdb/components/useUniqueId.test.ts b/public/app/plugins/datasource/influxdb/components/useUniqueId.test.ts deleted file mode 100644 index 98b3dd63b67..00000000000 --- a/public/app/plugins/datasource/influxdb/components/useUniqueId.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { renderHook } from '@testing-library/react'; - -import { useUniqueId } from './useUniqueId'; - -describe('useUniqueId', () => { - it('should work correctly', () => { - const { result: resultA, rerender: rerenderA } = renderHook(() => useUniqueId()); - const { result: resultB, rerender: rerenderB } = renderHook(() => useUniqueId()); - - // the values of the separate hooks should be different - expect(resultA.current).not.toBe(resultB.current); - - // we copy the current values after the first render - const firstValueA = resultA.current; - const firstValueB = resultB.current; - - rerenderA(); - rerenderB(); - - // we check that the value did not change - expect(resultA.current).toBe(firstValueA); - expect(resultB.current).toBe(firstValueB); - }); -}); diff --git a/public/app/plugins/datasource/influxdb/components/useUniqueId.ts b/public/app/plugins/datasource/influxdb/components/useUniqueId.ts deleted file mode 100644 index 6ff4ab7c4b0..00000000000 --- a/public/app/plugins/datasource/influxdb/components/useUniqueId.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { uniqueId } from 'lodash'; -import { useRef } from 'react'; - -export function useUniqueId(): string { - // we need to lazy-init this ref. - // otherwise we would call `uniqueId` - // on every render. unfortunately - // useRef does not have lazy-init builtin, - // like useState does. we do it manually. - const idRefLazy = useRef(null); - - if (idRefLazy.current == null) { - idRefLazy.current = uniqueId(); - } - - return idRefLazy.current; -} diff --git a/public/app/plugins/datasource/opentsdb/components/OpenTsdbDetails.tsx b/public/app/plugins/datasource/opentsdb/components/OpenTsdbDetails.tsx index ed7164d1783..ef6e1946b46 100644 --- a/public/app/plugins/datasource/opentsdb/components/OpenTsdbDetails.tsx +++ b/public/app/plugins/datasource/opentsdb/components/OpenTsdbDetails.tsx @@ -1,9 +1,8 @@ -import React, { SyntheticEvent } from 'react'; +import React, { SyntheticEvent, useId } from 'react'; import { DataSourceSettings, SelectableValue } from '@grafana/data'; import { InlineFormLabel, LegacyForms } from '@grafana/ui'; -import { useUniqueId } from '../../influxdb/components/useUniqueId'; import { OpenTsdbOptions } from '../types'; const { Select, Input } = LegacyForms; @@ -27,7 +26,7 @@ interface Props { export const OpenTsdbDetails = (props: Props) => { const { onChange, value } = props; - const idSuffix = useUniqueId(); + const idSuffix = useId(); return ( <>