Chore: Avoid explicit React.FC<Props> when possible (round 2) (#64749)

This commit is contained in:
Ryan McKinley
2023-03-15 07:56:09 -07:00
committed by GitHub
parent 1a16636692
commit 4f13e78d11
147 changed files with 364 additions and 449 deletions

View File

@@ -44,7 +44,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
};
});
export const ButtonCascader: React.FC<ButtonCascaderProps> = (props) => {
export const ButtonCascader = (props: ButtonCascaderProps) => {
const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props;
const theme = useTheme2();
const styles = getStyles(theme);

View File

@@ -21,8 +21,8 @@ export interface ContextMenuProps {
renderHeader?: () => React.ReactNode;
}
export const ContextMenu: React.FC<ContextMenuProps> = React.memo(
({ x, y, onClose, focusOnOpen = true, renderMenuItems, renderHeader }) => {
export const ContextMenu = React.memo(
({ x, y, onClose, focusOnOpen = true, renderMenuItems, renderHeader }: ContextMenuProps) => {
const menuRef = useRef<HTMLDivElement>(null);
const [positionStyles, setPositionStyles] = useState({});

View File

@@ -11,7 +11,7 @@ export interface WithContextMenuProps {
focusOnOpen?: boolean;
}
export const WithContextMenu: React.FC<WithContextMenuProps> = ({ children, renderMenuItems, focusOnOpen = true }) => {
export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true }: WithContextMenuProps) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
return (

View File

@@ -30,48 +30,46 @@ const getStyles = (theme: GrafanaTheme2) => ({
`,
});
export const DataLinkEditor: React.FC<DataLinkEditorProps> = React.memo(
({ index, value, onChange, suggestions, isLast }) => {
const styles = useStyles2(getStyles);
export const DataLinkEditor = React.memo(({ index, value, onChange, suggestions, isLast }: DataLinkEditorProps) => {
const styles = useStyles2(getStyles);
const onUrlChange = (url: string, callback?: () => void) => {
onChange(index, { ...value, url }, callback);
};
const onTitleChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange(index, { ...value, title: event.target.value });
};
const onUrlChange = (url: string, callback?: () => void) => {
onChange(index, { ...value, url }, callback);
};
const onTitleChange = (event: ChangeEvent<HTMLInputElement>) => {
onChange(index, { ...value, title: event.target.value });
};
const onOpenInNewTabChanged = () => {
onChange(index, { ...value, targetBlank: !value.targetBlank });
};
const onOpenInNewTabChanged = () => {
onChange(index, { ...value, targetBlank: !value.targetBlank });
};
return (
<div className={styles.listItem}>
<Field label="Title">
<Input value={value.title} onChange={onTitleChange} placeholder="Show details" />
</Field>
return (
<div className={styles.listItem}>
<Field label="Title">
<Input value={value.title} onChange={onTitleChange} placeholder="Show details" />
</Field>
<Field
label="URL"
invalid={isCompactUrl(value.url)}
error="Data link is an Explore URL in a deprecated format. Please visit the URL to be redirected, and edit this data link to use that URL."
>
<DataLinkInput value={value.url} onChange={onUrlChange} suggestions={suggestions} />
</Field>
<Field
label="URL"
invalid={isCompactUrl(value.url)}
error="Data link is an Explore URL in a deprecated format. Please visit the URL to be redirected, and edit this data link to use that URL."
>
<DataLinkInput value={value.url} onChange={onUrlChange} suggestions={suggestions} />
</Field>
<Field label="Open in new tab">
<Switch value={value.targetBlank || false} onChange={onOpenInNewTabChanged} />
</Field>
<Field label="Open in new tab">
<Switch value={value.targetBlank || false} onChange={onOpenInNewTabChanged} />
</Field>
{isLast && (
<div className={styles.infoText}>
With data links you can reference data variables like series name, labels and values. Type CMD+Space,
CTRL+Space, or $ to open variable suggestions.
</div>
)}
</div>
);
}
);
{isLast && (
<div className={styles.infoText}>
With data links you can reference data variables like series name, labels and values. Type CMD+Space,
CTRL+Space, or $ to open variable suggestions.
</div>
)}
</div>
);
});
DataLinkEditor.displayName = 'DataLinkEditor';

View File

@@ -72,8 +72,13 @@ const getStyles = (theme: GrafanaTheme2) => ({
// This memoised also because rerendering the slate editor grabs focus which created problem in some cases this
// was used and changes to different state were propagated here.
export const DataLinkInput: React.FC<DataLinkInputProps> = memo(
({ value, onChange, suggestions, placeholder = 'http://your-grafana.com/d/000000010/annotations' }) => {
export const DataLinkInput = memo(
({
value,
onChange,
suggestions,
placeholder = 'http://your-grafana.com/d/000000010/annotations',
}: DataLinkInputProps) => {
const editorRef = useRef<Editor>(null);
const styles = useStyles2(getStyles);
const [showingSuggestions, setShowingSuggestions] = useState(false);

View File

@@ -53,7 +53,7 @@ const getStyles = (theme: GrafanaTheme2) => {
};
};
export const DataLinkSuggestions: React.FC<DataLinkSuggestionsProps> = ({ suggestions, ...otherProps }) => {
export const DataLinkSuggestions = ({ suggestions, ...otherProps }: DataLinkSuggestionsProps) => {
const ref = useRef(null);
useClickAway(ref, () => {
@@ -104,8 +104,16 @@ interface DataLinkSuggestionsListProps extends DataLinkSuggestionsProps {
activeRef?: React.RefObject<HTMLDivElement>;
}
const DataLinkSuggestionsList: React.FC<DataLinkSuggestionsListProps> = React.memo(
({ activeIndex, activeIndexOffset, label, onClose, onSuggestionSelect, suggestions, activeRef: selectedRef }) => {
const DataLinkSuggestionsList = React.memo(
({
activeIndex,
activeIndexOffset,
label,
onClose,
onSuggestionSelect,
suggestions,
activeRef: selectedRef,
}: DataLinkSuggestionsListProps) => {
const styles = useStyles2(getStyles);
return (

View File

@@ -18,12 +18,7 @@ interface DataLinksInlineEditorProps {
data: DataFrame[];
}
export const DataLinksInlineEditor: React.FC<DataLinksInlineEditorProps> = ({
links,
onChange,
getSuggestions,
data,
}) => {
export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => {
const theme = useTheme2();
const [editIndex, setEditIndex] = useState<number | null>(null);
const [isNew, setIsNew] = useState(false);

View File

@@ -6,7 +6,7 @@ import { SecretFormField } from '../SecretFormField/SecretFormField';
import { HttpSettingsProps } from './types';
export const BasicAuthSettings: React.FC<HttpSettingsProps> = ({ dataSourceConfig, onChange }) => {
export const BasicAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsProps) => {
const password = dataSourceConfig.secureJsonData ? dataSourceConfig.secureJsonData.basicAuthPassword : '';
const onPasswordReset = () => {

View File

@@ -55,7 +55,7 @@ const getCustomHeaderRowStyles = stylesFactory(() => {
};
});
const CustomHeaderRow: React.FC<CustomHeaderRowProps> = ({ header, onBlur, onChange, onRemove, onReset }) => {
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => {
const styles = getCustomHeaderRowStyles();
return (
<div className={styles.layout}>

View File

@@ -61,7 +61,7 @@ const HttpAccessHelp = () => (
const LABEL_WIDTH = 26;
export const DataSourceHttpSettings: React.FC<HttpSettingsProps> = (props) => {
export const DataSourceHttpSettings = (props: HttpSettingsProps) => {
const {
defaultUrl,
dataSourceConfig,

View File

@@ -7,11 +7,11 @@ import { HttpSettingsBaseProps } from './types';
const LABEL_WIDTH = 26;
export const HttpProxySettings: React.FC<HttpSettingsBaseProps> = ({
export const HttpProxySettings = ({
dataSourceConfig,
onChange,
showForwardOAuthIdentityOption = true,
}) => {
}: HttpSettingsBaseProps) => {
return (
<>
<div className="gf-form-inline">

View File

@@ -10,7 +10,7 @@ import { Tooltip } from '../Tooltip/Tooltip';
import { CertificationKey } from './CertificationKey';
import { HttpSettingsBaseProps } from './types';
export const TLSAuthSettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceConfig, onChange }) => {
export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBaseProps) => {
const hasTLSCACert = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsCACert;
const hasTLSClientCert = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsClientCert;
const hasTLSClientKey = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsClientKey;

View File

@@ -7,7 +7,7 @@ import { RelativeTimeRange } from '@grafana/data';
import { RelativeTimeRangePicker } from './RelativeTimeRangePicker';
function setup(initial: RelativeTimeRange = { from: 900, to: 0 }): RenderResult {
const StatefulPicker: React.FC<{}> = () => {
const StatefulPicker = () => {
const [value, setValue] = useState<RelativeTimeRange>(initial);
return <RelativeTimeRangePicker timeRange={value} onChange={setValue} />;
};

View File

@@ -43,7 +43,7 @@ interface FormProps extends Omit<Props, 'history'> {
historyOptions?: TimeOption[];
}
export const TimePickerContentWithScreenSize: React.FC<PropsWithScreenSize> = (props) => {
export const TimePickerContentWithScreenSize = (props: PropsWithScreenSize) => {
const {
quickOptions = [],
isReversed,
@@ -174,7 +174,7 @@ const NarrowScreenForm = (props: FormProps) => {
);
};
const FullScreenForm: React.FC<FormProps> = (props) => {
const FullScreenForm = (props: FormProps) => {
const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props;
const theme = useTheme2();
const styles = getFullScreenStyles(theme, props.hideQuickRanges);

View File

@@ -26,7 +26,7 @@ export interface SelectableZone extends SelectableValue<string> {
searchIndex: string;
}
export const WideTimeZoneOption: React.FC<PropsWithChildren<Props>> = (props, ref) => {
export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
const theme = useTheme2();
const styles = getStyles(theme);
@@ -66,7 +66,7 @@ export const WideTimeZoneOption: React.FC<PropsWithChildren<Props>> = (props, re
);
};
export const CompactTimeZoneOption: React.FC<React.PropsWithChildren<Props>> = (props, ref) => {
export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) => {
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
const theme = useTheme2();
const styles = getStyles(theme);

View File

@@ -15,7 +15,7 @@ export interface FilterPillProps {
icon?: IconName;
}
export const FilterPill: React.FC<FilterPillProps> = ({ label, selected, onClick, icon = 'check' }) => {
export const FilterPill = ({ label, selected, onClick, icon = 'check' }: FilterPillProps) => {
const styles = useStyles2(getStyles);
const clearButton = useStyles2(clearButtonStyles);
return (

View File

@@ -69,7 +69,7 @@ export const getFieldStyles = stylesFactory((theme: GrafanaTheme2) => {
};
});
export const Field: React.FC<FieldProps> = ({
export const Field = ({
label,
description,
horizontal,
@@ -83,7 +83,7 @@ export const Field: React.FC<FieldProps> = ({
validationMessageHorizontalOverflow,
htmlFor,
...otherProps
}) => {
}: FieldProps) => {
const theme = useTheme2();
const styles = getFieldStyles(theme);
const inputId = htmlFor ?? getChildId(children);

View File

@@ -46,7 +46,7 @@ export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => {
};
});
export const Label: React.FC<LabelProps> = ({ children, description, className, category, ...labelProps }) => {
export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => {
const theme = useTheme2();
const styles = getLabelStyles(theme);
const categories = category?.map((c, i) => {

View File

@@ -20,7 +20,7 @@ export const getLegendStyles = (theme: GrafanaTheme2) => {
};
};
export const Legend: React.FC<LabelProps> = ({ children, className, ...legendProps }) => {
export const Legend = ({ children, className, ...legendProps }: LabelProps) => {
const styles = useStyles2(getLegendStyles);
return (

View File

@@ -115,7 +115,7 @@ DisabledList.args = {
};
export const Dots: Story = () => {
const Wrapper: React.FC<React.PropsWithChildren<{ title: string }>> = ({ title, children }) => (
const Wrapper = ({ title, children }: React.PropsWithChildren<{ title: string }>) => (
<div style={{ marginBottom: 20 }}>
<h5>{title}</h5>
{children}

View File

@@ -32,14 +32,14 @@ export type GraphContextMenuProps = ContextMenuProps & {
};
/** @internal */
export const GraphContextMenu: React.FC<GraphContextMenuProps> = ({
export const GraphContextMenu = ({
getContextMenuSource,
timeZone,
itemsGroup,
dimensions,
contextDimensions,
...otherProps
}) => {
}: GraphContextMenuProps) => {
const source = getContextMenuSource();
// Do not render items that do not have label specified

View File

@@ -8,12 +8,12 @@ import { getMultiSeriesGraphHoverInfo } from '../utils';
import { GraphTooltipContentProps } from './types';
export const MultiModeGraphTooltip: React.FC<
GraphTooltipContentProps & {
// We expect position to figure out correct values when not hovering over a datapoint
pos: FlotPosition;
}
> = ({ dimensions, activeDimensions, pos, timeZone }) => {
type Props = GraphTooltipContentProps & {
// We expect position to figure out correct values when not hovering over a datapoint
pos: FlotPosition;
};
export const MultiModeGraphTooltip = ({ dimensions, activeDimensions, pos, timeZone }: Props) => {
let activeSeriesIndex: number | null = null;
// when no x-axis provided, skip rendering
if (activeDimensions.xAxis === null) {

View File

@@ -11,11 +11,7 @@ import { SeriesTable } from '../../VizTooltip';
import { GraphTooltipContentProps } from './types';
export const SingleModeGraphTooltip: React.FC<GraphTooltipContentProps> = ({
dimensions,
activeDimensions,
timeZone,
}) => {
export const SingleModeGraphTooltip = ({ dimensions, activeDimensions, timeZone }: GraphTooltipContentProps) => {
// not hovering over a point, skip rendering
if (
activeDimensions.yAxis === null ||

View File

@@ -47,7 +47,7 @@ interface FeatureBadgeProps {
tooltip?: string;
}
export const FeatureBadge: React.FC<FeatureBadgeProps> = ({ featureState, tooltip }) => {
export const FeatureBadge = ({ featureState, tooltip }: FeatureBadgeProps) => {
const display = getPanelStateBadgeDisplayModel(featureState);
return <Badge text={display.text} color={display.color} icon={display.icon} tooltip={tooltip} />;
};

View File

@@ -25,7 +25,7 @@ export interface MenuGroupProps extends Partial<MenuItemsGroup> {
}
/** @internal */
export const MenuGroup: React.FC<MenuGroupProps> = ({ label, ariaLabel, children }) => {
export const MenuGroup = ({ label, ariaLabel, children }: MenuGroupProps) => {
const styles = useStyles2(getStyles);
const labelID = `group-label-${uniqueId()}`;

View File

@@ -28,8 +28,8 @@ export interface SubMenuProps {
}
/** @internal */
export const SubMenu: React.FC<SubMenuProps> = React.memo(
({ items, isOpen, openedWithArrow, setOpenedWithArrow, close, customStyle }) => {
export const SubMenu = React.memo(
({ items, isOpen, openedWithArrow, setOpenedWithArrow, close, customStyle }: SubMenuProps) => {
const styles = useStyles2(getStyles);
const localRef = useRef<HTMLDivElement>(null);
const [handleKeys] = useMenuFocus({

View File

@@ -17,7 +17,7 @@ export type ErrorIndicatorProps = {
/**
* @internal
*/
export const ErrorIndicator: React.FC<ErrorIndicatorProps> = ({ error, onClick }) => {
export const ErrorIndicator = ({ error, onClick }: ErrorIndicatorProps) => {
const styles = useStyles2(getStyles);
if (!error) {

View File

@@ -18,7 +18,7 @@ export type LoadingIndicatorProps = {
/**
* @internal
*/
export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({ onCancel, loading }) => {
export const LoadingIndicator = ({ onCancel, loading }: LoadingIndicatorProps) => {
const styles = useStyles2(getStyles);
if (!loading) {

View File

@@ -14,7 +14,7 @@ export interface PluginSignatureBadgeProps extends HTMLAttributes<HTMLDivElement
/**
* @public
*/
export const PluginSignatureBadge: React.FC<PluginSignatureBadgeProps> = ({ status, ...otherProps }) => {
export const PluginSignatureBadge = ({ status, ...otherProps }: PluginSignatureBadgeProps) => {
const display = getSignatureDisplayModel(status);
return (
<Badge

View File

@@ -25,7 +25,7 @@ export const useExpandableLabel = (
}
};
const Label: React.FC<LabelProps> = ({ Component, onClick, disabled }) => (
const Label = ({ Component, onClick, disabled }: LabelProps) => (
<button
type="button"
className={buttonStyles}

View File

@@ -6,7 +6,7 @@ interface DropdownIndicatorProps {
isOpen: boolean;
}
export const DropdownIndicator: React.FC<DropdownIndicatorProps> = ({ isOpen }) => {
export const DropdownIndicator = ({ isOpen }: DropdownIndicatorProps) => {
const icon = isOpen ? 'search' : 'angle-down';
const size = isOpen ? 'sm' : 'md';
return <Icon name={icon} size={size} />;

View File

@@ -52,7 +52,7 @@ const getSeriesTableRowStyles = (theme: GrafanaTheme2) => {
/**
* @public
*/
export const SeriesTableRow: React.FC<SeriesTableRowProps> = ({ color, label, value, isActive }) => {
export const SeriesTableRow = ({ color, label, value, isActive }: SeriesTableRowProps) => {
const styles = useStyles2(getSeriesTableRowStyles);
return (
@@ -79,7 +79,7 @@ export interface SeriesTableProps {
/**
* @public
*/
export const SeriesTable: React.FC<SeriesTableProps> = ({ timestamp, series }) => {
export const SeriesTable = ({ timestamp, series }: SeriesTableProps) => {
const styles = useStyles2(getSeriesTableRowStyles);
return (

View File

@@ -22,14 +22,14 @@ export interface VizTooltipContainerProps extends HTMLAttributes<HTMLDivElement>
/**
* @public
*/
export const VizTooltipContainer: React.FC<VizTooltipContainerProps> = ({
export const VizTooltipContainer = ({
position: { x: positionX, y: positionY },
offset: { x: offsetX, y: offsetY },
children,
allowPointerEvents = false,
className,
...otherProps
}) => {
}: VizTooltipContainerProps) => {
const tooltipRef = useRef<HTMLDivElement>(null);
const [tooltipMeasurement, setTooltipMeasurement] = useState<Dimensions2D>({ width: 0, height: 0 });
const { width, height } = useWindowSize();

View File

@@ -27,8 +27,8 @@ interface PlotLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, '
config: UPlotConfigBuilder;
}
export const PlotLegend: React.FC<PlotLegendProps> = React.memo(
({ data, config, placement, calcs, displayMode, ...vizLayoutLegendProps }) => {
export const PlotLegend = React.memo(
({ data, config, placement, calcs, displayMode, ...vizLayoutLegendProps }: PlotLegendProps) => {
const theme = useTheme2();
const legendItems = config
.getSeries()

View File

@@ -1,5 +1,5 @@
import { clamp } from 'lodash';
import React, { useLayoutEffect } from 'react';
import { useLayoutEffect } from 'react';
import uPlot from 'uplot';
import { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';
@@ -170,7 +170,7 @@ const initHook = (u: uPlot) => {
/**
* @alpha
*/
export const KeyboardPlugin: React.FC<KeyboardPluginProps> = ({ config }) => {
export const KeyboardPlugin = ({ config }: KeyboardPluginProps) => {
useLayoutEffect(() => config.addHook('init', initHook), [config]);
return null;

View File

@@ -40,7 +40,7 @@ const TOOLTIP_OFFSET = 10;
/**
* @alpha
*/
export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
export const TooltipPlugin = ({
mode = TooltipDisplayMode.Single,
sortOrder = SortOrder.None,
sync,
@@ -48,7 +48,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
config,
renderTooltip,
...otherProps
}) => {
}: TooltipPluginProps) => {
const plotInstance = useRef<uPlot>();
const theme = useTheme2();
const [focusedSeriesIdx, setFocusedSeriesIdx] = useState<number | null>(null);

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useLayoutEffect, useState } from 'react';
import { useEffect, useLayoutEffect, useState } from 'react';
import { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';
import { PlotSelection } from '../types';
@@ -15,7 +15,7 @@ const MIN_ZOOM_DIST = 5;
/**
* @alpha
*/
export const ZoomPlugin: React.FC<ZoomPluginProps> = ({ onZoom, config }) => {
export const ZoomPlugin = ({ onZoom, config }: ZoomPluginProps) => {
const [selection, setSelection] = useState<PlotSelection | null>(null);
useEffect(() => {

View File

@@ -6,9 +6,7 @@ import { HideableFieldConfig, HideSeriesConfig } from '@grafana/schema';
import { FilterPill, HorizontalGroup } from '../../index';
const SeriesConfigEditor: React.FC<FieldConfigEditorProps<HideSeriesConfig, {}>> = (props) => {
const { value, onChange } = props;
const SeriesConfigEditor = ({ value, onChange }: FieldConfigEditorProps<HideSeriesConfig, {}>) => {
const onChangeToggle = useCallback(
(prop: keyof HideSeriesConfig) => {
onChange({ ...value, [prop]: !value[prop] });

View File

@@ -18,12 +18,7 @@ import {
Tooltip,
} from '../..';
export const StackingEditor: React.FC<FieldOverrideEditorProps<StackingConfig, any>> = ({
value,
context,
onChange,
item,
}) => {
export const StackingEditor = ({ value, context, onChange, item }: FieldOverrideEditorProps<StackingConfig, any>) => {
return (
<HorizontalGroup>
<RadioButtonGroup

View File

@@ -34,7 +34,7 @@ describe('useStyles', () => {
});
it('passes in theme and returns style object', (done) => {
const Dummy: React.FC = function () {
const Dummy = function () {
const styles = useStyles2((theme) => {
return {
someStyle: css`

View File

@@ -8,9 +8,10 @@ import { GrafanaLight, GrafanaDark } from '../../../.storybook/storybookTheme';
type Props = {
context: DocsContextProps;
children?: React.ReactNode;
};
export const ThemedDocsContainer: React.FC<Props> = ({ children, context }) => {
export const ThemedDocsContainer = ({ children, context }: Props) => {
const dark = useDarkMode();
return (