Use FunctionComponent type for components needing 'children' prop (#977)

This commit is contained in:
Jon Koops 2021-08-10 13:18:48 +02:00 committed by GitHub
parent 190376590f
commit 45bd2fd385
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 61 additions and 60 deletions

View file

@ -1,4 +1,4 @@
import React, { ReactNode, useEffect } from "react"; import React, { FunctionComponent, useEffect } from "react";
import { Page } from "@patternfly/react-core"; import { Page } from "@patternfly/react-core";
import { import {
HashRouter as Router, HashRouter as Router,
@ -25,7 +25,7 @@ import { ErrorRenderer } from "./components/error/ErrorRenderer";
export const mainPageContentId = "kc-main-content-page-container"; export const mainPageContentId = "kc-main-content-page-container";
const AppContexts = ({ children }: { children: ReactNode }) => ( const AppContexts: FunctionComponent = ({ children }) => (
<AccessContextProvider> <AccessContextProvider>
<Help> <Help>
<AlertProvider> <AlertProvider>
@ -38,7 +38,7 @@ const AppContexts = ({ children }: { children: ReactNode }) => (
); );
// set the realm form the path // set the realm form the path
const RealmPathSelector = ({ children }: { children: ReactNode }) => { const RealmPathSelector: FunctionComponent = ({ children }) => {
const { setRealm } = useRealm(); const { setRealm } = useRealm();
const { realm } = useParams<{ realm: string }>(); const { realm } = useParams<{ realm: string }>();
useEffect(() => { useEffect(() => {

View file

@ -1,4 +1,4 @@
import React, { createContext, ReactNode, useState } from "react"; import React, { createContext, FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { AlertVariant } from "@patternfly/react-core"; import { AlertVariant } from "@patternfly/react-core";
import type { AxiosError } from "axios"; import type { AxiosError } from "axios";
@ -20,7 +20,7 @@ export const AlertContext = createContext<AlertProps | undefined>(undefined);
export const useAlerts = () => useRequiredContext(AlertContext); export const useAlerts = () => useRequiredContext(AlertContext);
export const AlertProvider = ({ children }: { children: ReactNode }) => { export const AlertProvider: FunctionComponent = ({ children }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [alerts, setAlerts] = useState<AlertType[]>([]); const [alerts, setAlerts] = useState<AlertType[]>([]);

View file

@ -1,7 +1,7 @@
import { render, waitFor } from "@testing-library/react"; import { render, waitFor } from "@testing-library/react";
import type KeycloakAdminClient from "keycloak-admin"; import type KeycloakAdminClient from "keycloak-admin";
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation"; import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
import React, { ReactNode } from "react"; import React, { FunctionComponent } from "react";
import { HashRouter } from "react-router-dom"; import { HashRouter } from "react-router-dom";
import { AccessContextProvider } from "../../context/access/Access"; import { AccessContextProvider } from "../../context/access/Access";
import { AdminClient } from "../../context/auth/AdminClient"; import { AdminClient } from "../../context/auth/AdminClient";
@ -25,10 +25,9 @@ import { DataLoader } from "./DataLoader";
* </MockAdminClient> * </MockAdminClient>
* @param props mock endpoints to be mocked * @param props mock endpoints to be mocked
*/ */
export const MockAdminClient = (props: { export const MockAdminClient: FunctionComponent<{ mock?: object }> = (
children: ReactNode; props
mock?: object; ) => {
}) => {
return ( return (
<HashRouter> <HashRouter>
<ServerInfoContext.Provider <ServerInfoContext.Provider

View file

@ -1,6 +1,7 @@
import React, { import React, {
Children, Children,
cloneElement, cloneElement,
FunctionComponent,
isValidElement, isValidElement,
ReactElement, ReactElement,
ReactNode, ReactNode,
@ -40,20 +41,19 @@ export type FormAccessProps = FormProps & {
* @type {boolean} * @type {boolean}
*/ */
unWrap?: boolean; unWrap?: boolean;
children: ReactNode;
}; };
/** /**
* Use this in place of a patternfly Form component and add the `role` and `fineGrainedAccess` properties. * Use this in place of a patternfly Form component and add the `role` and `fineGrainedAccess` properties.
* @param {FormAccessProps} param0 - all properties of Form + role and fineGrainedAccess * @param {FormAccessProps} param0 - all properties of Form + role and fineGrainedAccess
*/ */
export const FormAccess = ({ export const FormAccess: FunctionComponent<FormAccessProps> = ({
children, children,
role, role,
fineGrainedAccess = false, fineGrainedAccess = false,
unWrap = false, unWrap = false,
...rest ...rest
}: FormAccessProps) => { }) => {
const { hasAccess } = useAccess(); const { hasAccess } = useAccess();
const recursiveCloneChildren = ( const recursiveCloneChildren = (

View file

@ -9,15 +9,11 @@ import {
TextContent, TextContent,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { ExternalLinkAltIcon, HelpIcon } from "@patternfly/react-icons"; import { ExternalLinkAltIcon, HelpIcon } from "@patternfly/react-icons";
import React, { createContext, ReactNode, useState } from "react"; import React, { createContext, FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useRequiredContext from "../../utils/useRequiredContext"; import useRequiredContext from "../../utils/useRequiredContext";
import "./help-header.css"; import "./help-header.css";
type HelpProps = {
children: ReactNode;
};
type HelpContextProps = { type HelpContextProps = {
enabled: boolean; enabled: boolean;
toggleHelp: () => void; toggleHelp: () => void;
@ -29,7 +25,7 @@ export const HelpContext = createContext<HelpContextProps | undefined>(
export const useHelp = () => useRequiredContext(HelpContext); export const useHelp = () => useRequiredContext(HelpContext);
export const Help = ({ children }: HelpProps) => { export const Help: FunctionComponent = ({ children }) => {
const [enabled, setHelp] = useState(true); const [enabled, setHelp] = useState(true);
function toggleHelp() { function toggleHelp() {

View file

@ -1,4 +1,4 @@
import React, { ReactNode } from "react"; import React, { FunctionComponent } from "react";
import { import {
Card, Card,
CardBody, CardBody,
@ -12,16 +12,15 @@ import "./form-panel.css";
type FormPanelProps = { type FormPanelProps = {
title: string; title: string;
scrollId?: string; scrollId?: string;
children: ReactNode;
className?: string; className?: string;
}; };
export const FormPanel = ({ export const FormPanel: FunctionComponent<FormPanelProps> = ({
title, title,
children, children,
scrollId, scrollId,
className, className,
}: FormPanelProps) => { }) => {
return ( return (
<Card className={className} isFlat> <Card className={className} isFlat>
<CardHeader className="kc-form-panel__header"> <CardHeader className="kc-form-panel__header">

View file

@ -1,4 +1,4 @@
import React, { Children, Fragment } from "react"; import React, { Children, Fragment, FunctionComponent } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import {
Grid, Grid,
@ -18,19 +18,18 @@ import "./scroll-form.css";
type ScrollFormProps = GridProps & { type ScrollFormProps = GridProps & {
sections: string[]; sections: string[];
borders?: boolean; borders?: boolean;
children: React.ReactNode;
}; };
const spacesToHyphens = (string: string): string => { const spacesToHyphens = (string: string): string => {
return string.replace(/\s+/g, "-"); return string.replace(/\s+/g, "-");
}; };
export const ScrollForm = ({ export const ScrollForm: FunctionComponent<ScrollFormProps> = ({
sections, sections,
borders = false, borders = false,
children, children,
...rest ...rest
}: ScrollFormProps) => { }) => {
const { t } = useTranslation("common"); const { t } = useTranslation("common");
const nodes = Children.toArray(children); const nodes = Children.toArray(children);

View file

@ -1,4 +1,4 @@
import React, { HTMLProps, ReactNode } from "react"; import React, { FunctionComponent, HTMLProps } from "react";
import { Title } from "@patternfly/react-core"; import { Title } from "@patternfly/react-core";
import "./form-panel.css"; import "./form-panel.css";
@ -6,10 +6,9 @@ import "./form-panel.css";
type ScrollPanelProps = HTMLProps<HTMLFormElement> & { type ScrollPanelProps = HTMLProps<HTMLFormElement> & {
title: string; title: string;
scrollId: string; scrollId: string;
children: ReactNode;
}; };
export const ScrollPanel = (props: ScrollPanelProps) => { export const ScrollPanel: FunctionComponent<ScrollPanelProps> = (props) => {
const { title, children, scrollId, ...rest } = props; const { title, children, scrollId, ...rest } = props;
return ( return (
<section {...rest} className="kc-form-panel__panel"> <section {...rest} className="kc-form-panel__panel">

View file

@ -1,4 +1,4 @@
import React, { FormEvent, ReactNode } from "react"; import React, { FormEvent, FunctionComponent, ReactNode } from "react";
import { import {
Pagination, Pagination,
ToggleTemplateProps, ToggleTemplateProps,
@ -16,7 +16,6 @@ type TableToolbarProps = {
searchTypeComponent?: ReactNode; searchTypeComponent?: ReactNode;
toolbarItem?: ReactNode; toolbarItem?: ReactNode;
subToolbar?: ReactNode; subToolbar?: ReactNode;
children: ReactNode;
inputGroupName?: string; inputGroupName?: string;
inputGroupPlaceholder?: string; inputGroupPlaceholder?: string;
inputGroupOnChange?: ( inputGroupOnChange?: (
@ -26,7 +25,7 @@ type TableToolbarProps = {
inputGroupOnEnter?: (value: string) => void; inputGroupOnEnter?: (value: string) => void;
}; };
export const PaginatingTableToolbar = ({ export const PaginatingTableToolbar: FunctionComponent<TableToolbarProps> = ({
count, count,
first, first,
max, max,
@ -41,7 +40,7 @@ export const PaginatingTableToolbar = ({
inputGroupPlaceholder, inputGroupPlaceholder,
inputGroupOnChange, inputGroupOnChange,
inputGroupOnEnter, inputGroupOnEnter,
}: TableToolbarProps) => { }) => {
const page = Math.round(first / max); const page = Math.round(first / max);
const pagination = (variant: "top" | "bottom" = "top") => ( const pagination = (variant: "top" | "bottom" = "top") => (
<Pagination <Pagination

View file

@ -1,4 +1,10 @@
import React, { FormEvent, Fragment, ReactNode, useState } from "react"; import React, {
FormEvent,
Fragment,
FunctionComponent,
ReactNode,
useState,
} from "react";
import { import {
Toolbar, Toolbar,
ToolbarContent, ToolbarContent,
@ -16,7 +22,6 @@ type TableToolbarProps = {
toolbarItem?: ReactNode; toolbarItem?: ReactNode;
subToolbar?: ReactNode; subToolbar?: ReactNode;
toolbarItemFooter?: ReactNode; toolbarItemFooter?: ReactNode;
children: ReactNode;
searchTypeComponent?: ReactNode; searchTypeComponent?: ReactNode;
inputGroupName?: string; inputGroupName?: string;
inputGroupPlaceholder?: string; inputGroupPlaceholder?: string;
@ -27,7 +32,7 @@ type TableToolbarProps = {
inputGroupOnEnter?: (value: string) => void; inputGroupOnEnter?: (value: string) => void;
}; };
export const TableToolbar = ({ export const TableToolbar: FunctionComponent<TableToolbarProps> = ({
toolbarItem, toolbarItem,
subToolbar, subToolbar,
toolbarItemFooter, toolbarItemFooter,
@ -37,7 +42,7 @@ export const TableToolbar = ({
inputGroupPlaceholder, inputGroupPlaceholder,
inputGroupOnChange, inputGroupOnChange,
inputGroupOnEnter, inputGroupOnEnter,
}: TableToolbarProps) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [searchValue, setSearchValue] = useState<string>(""); const [searchValue, setSearchValue] = useState<string>("");

View file

@ -1,5 +1,10 @@
import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation"; import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
import React, { createContext, useEffect, useState } from "react"; import React, {
createContext,
FunctionComponent,
useEffect,
useState,
} from "react";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useWhoAmI } from "../../context/whoami/WhoAmI"; import { useWhoAmI } from "../../context/whoami/WhoAmI";
import useRequiredContext from "../../utils/useRequiredContext"; import useRequiredContext from "../../utils/useRequiredContext";
@ -15,8 +20,7 @@ export const AccessContext = createContext<AccessContextProps | undefined>(
export const useAccess = () => useRequiredContext(AccessContext); export const useAccess = () => useRequiredContext(AccessContext);
type AccessProviderProps = { children: React.ReactNode }; export const AccessContextProvider: FunctionComponent = ({ children }) => {
export const AccessContextProvider = ({ children }: AccessProviderProps) => {
const { whoAmI } = useWhoAmI(); const { whoAmI } = useWhoAmI();
const { realm } = useRealm(); const { realm } = useRealm();
const [access, setAccess] = useState<readonly AccessType[]>([]); const [access, setAccess] = useState<readonly AccessType[]>([]);

View file

@ -1,6 +1,6 @@
import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation"; import type RealmRepresentation from "keycloak-admin/lib/defs/realmRepresentation";
import _ from "lodash"; import _ from "lodash";
import React, { useState } from "react"; import React, { FunctionComponent, useState } from "react";
import { RecentUsed } from "../../components/realm-selector/recent-used"; import { RecentUsed } from "../../components/realm-selector/recent-used";
import environment from "../../environment"; import environment from "../../environment";
import useRequiredContext from "../../utils/useRequiredContext"; import useRequiredContext from "../../utils/useRequiredContext";
@ -17,11 +17,7 @@ export const RealmContext = React.createContext<RealmContextType | undefined>(
undefined undefined
); );
type RealmContextProviderProps = { children: React.ReactNode }; export const RealmContextProvider: FunctionComponent = ({ children }) => {
export const RealmContextProvider = ({
children,
}: RealmContextProviderProps) => {
const [realm, setRealm] = useState(environment.loginRealm); const [realm, setRealm] = useState(environment.loginRealm);
const [realms, setRealms] = useState<RealmRepresentation[]>([]); const [realms, setRealms] = useState<RealmRepresentation[]>([]);
const adminClient = useAdminClient(); const adminClient = useAdminClient();

View file

@ -1,5 +1,5 @@
import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation"; import type { ServerInfoRepresentation } from "keycloak-admin/lib/defs/serverInfoRepesentation";
import React, { createContext, ReactNode } from "react"; import React, { createContext, FunctionComponent } from "react";
import { DataLoader } from "../../components/data-loader/DataLoader"; import { DataLoader } from "../../components/data-loader/DataLoader";
import { sortProviders } from "../../util"; import { sortProviders } from "../../util";
import useRequiredContext from "../../utils/useRequiredContext"; import useRequiredContext from "../../utils/useRequiredContext";
@ -15,7 +15,7 @@ export const useLoginProviders = () => {
return sortProviders(useServerInfo().providers!["login-protocol"].providers); return sortProviders(useServerInfo().providers!["login-protocol"].providers);
}; };
export const ServerInfoProvider = ({ children }: { children: ReactNode }) => { export const ServerInfoProvider: FunctionComponent = ({ children }) => {
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const loader = async () => { const loader = async () => {
return await adminClient.serverInfo.find(); return await adminClient.serverInfo.find();

View file

@ -1,6 +1,6 @@
import type WhoAmIRepresentation from "keycloak-admin/lib/defs/whoAmIRepresentation"; import type WhoAmIRepresentation from "keycloak-admin/lib/defs/whoAmIRepresentation";
import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation"; import type { AccessType } from "keycloak-admin/lib/defs/whoAmIRepresentation";
import React, { useState } from "react"; import React, { FunctionComponent, useState } from "react";
import i18n from "../../i18n"; import i18n from "../../i18n";
import useRequiredContext from "../../utils/useRequiredContext"; import useRequiredContext from "../../utils/useRequiredContext";
import { useAdminClient, useFetch } from "../auth/AdminClient"; import { useAdminClient, useFetch } from "../auth/AdminClient";
@ -50,8 +50,7 @@ export const WhoAmIContext = React.createContext<WhoAmIProps | undefined>(
export const useWhoAmI = () => useRequiredContext(WhoAmIContext); export const useWhoAmI = () => useRequiredContext(WhoAmIContext);
type WhoAmIProviderProps = { children: React.ReactNode }; export const WhoAmIContextProvider: FunctionComponent = ({ children }) => {
export const WhoAmIContextProvider = ({ children }: WhoAmIProviderProps) => {
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const [whoAmI, setWhoAmI] = useState<WhoAmI>(new WhoAmI()); const [whoAmI, setWhoAmI] = useState<WhoAmI>(new WhoAmI());
const [key, setKey] = useState(0); const [key, setKey] = useState(0);

View file

@ -14,7 +14,7 @@ import {
} from "@patternfly/react-table"; } from "@patternfly/react-table";
import type AdminEventRepresentation from "keycloak-admin/lib/defs/adminEventRepresentation"; import type AdminEventRepresentation from "keycloak-admin/lib/defs/adminEventRepresentation";
import moment from "moment"; import moment from "moment";
import React, { ReactNode, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
@ -25,10 +25,13 @@ import { useRealm } from "../context/realm-context/RealmContext";
type DisplayDialogProps = { type DisplayDialogProps = {
titleKey: string; titleKey: string;
onClose: () => void; onClose: () => void;
children: ReactNode;
}; };
const DisplayDialog = ({ titleKey, onClose, children }: DisplayDialogProps) => { const DisplayDialog: FunctionComponent<DisplayDialogProps> = ({
titleKey,
onClose,
children,
}) => {
const { t } = useTranslation("events"); const { t } = useTranslation("events");
return ( return (
<Modal <Modal

View file

@ -1,5 +1,5 @@
import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation"; import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
import React, { createContext, ReactNode, useState } from "react"; import React, { createContext, FunctionComponent, useState } from "react";
import useRequiredContext from "../utils/useRequiredContext"; import useRequiredContext from "../utils/useRequiredContext";
type SubGroupsProps = { type SubGroupsProps = {
@ -12,7 +12,7 @@ type SubGroupsProps = {
const SubGroupContext = createContext<SubGroupsProps | undefined>(undefined); const SubGroupContext = createContext<SubGroupsProps | undefined>(undefined);
export const SubGroups = ({ children }: { children: ReactNode }) => { export const SubGroups: FunctionComponent = ({ children }) => {
const [subGroups, setSubGroups] = useState<GroupRepresentation[]>([]); const [subGroups, setSubGroups] = useState<GroupRepresentation[]>([]);
const clear = () => setSubGroups([]); const clear = () => setSubGroups([]);

View file

@ -1,13 +1,16 @@
import React, { ReactNode } from "react"; import React, { FunctionComponent } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormGroup } from "@patternfly/react-core"; import { FormGroup } from "@patternfly/react-core";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
export type FieldProps = { label: string; field: string; isReadOnly?: boolean }; export type FieldProps = { label: string; field: string; isReadOnly?: boolean };
export type FormGroupFieldProps = { label: string; children: ReactNode }; export type FormGroupFieldProps = { label: string };
export const FormGroupField = ({ label, children }: FormGroupFieldProps) => { export const FormGroupField: FunctionComponent<FormGroupFieldProps> = ({
label,
children,
}) => {
const { t } = useTranslation("identity-providers"); const { t } = useTranslation("identity-providers");
return ( return (
<FormGroup <FormGroup