diff --git a/packages/ra-core/src/auth/Authenticated.tsx b/packages/ra-core/src/auth/Authenticated.tsx index 0280d14ce2b..4aec39904b5 100644 --- a/packages/ra-core/src/auth/Authenticated.tsx +++ b/packages/ra-core/src/auth/Authenticated.tsx @@ -1,4 +1,4 @@ -import { cloneElement, ReactElement, FunctionComponent } from 'react'; +import { cloneElement, ReactElement } from 'react'; import useAuthenticated from './useAuthenticated'; @@ -36,12 +36,13 @@ interface Props { * * ); */ -const Authenticated: FunctionComponent = ({ - authParams, - children, - location, // kept for backwards compatibility, unused - ...rest -}) => { +const Authenticated = (props: Props) => { + const { + authParams, + children, + location, // kept for backwards compatibility, unused + ...rest + } = props; useAuthenticated(authParams); // render the child even though the useAuthenticated() call isn't finished (optimistic rendering) // the above hook will log out if the authProvider doesn't validate that the user is authenticated diff --git a/packages/ra-core/src/auth/WithPermissions.tsx b/packages/ra-core/src/auth/WithPermissions.tsx index 3d4cfb679fa..d9d16174f21 100644 --- a/packages/ra-core/src/auth/WithPermissions.tsx +++ b/packages/ra-core/src/auth/WithPermissions.tsx @@ -1,10 +1,4 @@ -import { - Children, - FunctionComponent, - ReactElement, - ComponentType, - createElement, -} from 'react'; +import { Children, ReactElement, ComponentType, createElement } from 'react'; import { Location } from 'history'; import warning from '../util/warning'; @@ -65,14 +59,15 @@ const isEmptyChildren = children => Children.count(children) === 0; * * ); */ -const WithPermissions: FunctionComponent = ({ - authParams, - children, - render, - component, - staticContext, - ...props -}) => { +const WithPermissions = (props: Props) => { + const { + authParams, + children, + render, + component, + staticContext, + ...rest + } = props; warning( (render && children && !isEmptyChildren(children)) || (render && component) || @@ -84,15 +79,15 @@ const WithPermissions: FunctionComponent = ({ const { permissions } = usePermissionsOptimized(authParams); // render even though the usePermissions() call isn't finished (optimistic rendering) if (component) { - return createElement(component, { permissions, ...props }); + return createElement(component, { permissions, ...rest }); } // @deprecated if (render) { - return render({ permissions, ...props }); + return render({ permissions, ...rest }); } // @deprecated if (children) { - return children({ permissions, ...props }); + return children({ permissions, ...rest }); } }; diff --git a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx index e82a6a4950e..a16d36371ba 100644 --- a/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx +++ b/packages/ra-core/src/controller/field/ReferenceArrayFieldController.tsx @@ -1,4 +1,4 @@ -import { FunctionComponent, ReactElement } from 'react'; +import { ReactElement } from 'react'; import useReferenceArrayFieldController from './useReferenceArrayFieldController'; import { ListControllerProps } from '../useListController'; @@ -22,7 +22,7 @@ interface Props { * * @see useReferenceArrayFieldController */ -const ReferenceArrayFieldController: FunctionComponent = props => { +const ReferenceArrayFieldController = (props: Props) => { const { children, ...rest } = props; const controllerProps = useReferenceArrayFieldController({ sort: { diff --git a/packages/ra-core/src/controller/field/ReferenceFieldController.tsx b/packages/ra-core/src/controller/field/ReferenceFieldController.tsx index 10c180fc088..d652637153a 100644 --- a/packages/ra-core/src/controller/field/ReferenceFieldController.tsx +++ b/packages/ra-core/src/controller/field/ReferenceFieldController.tsx @@ -1,4 +1,4 @@ -import { FunctionComponent, ReactNode, ReactElement } from 'react'; +import { ReactNode, ReactElement } from 'react'; import get from 'lodash/get'; import { Record } from '../../types'; @@ -49,12 +49,12 @@ interface Props { * * */ -export const ReferenceFieldController: FunctionComponent = ({ +export const ReferenceFieldController = ({ children, record, source, ...props -}) => { +}: Props) => { const id = get(record, source); return children({ ...useReference({ ...props, id }), diff --git a/packages/ra-core/src/controller/field/ReferenceManyFieldController.tsx b/packages/ra-core/src/controller/field/ReferenceManyFieldController.tsx index f3ec6f93a63..46baa2d6a69 100644 --- a/packages/ra-core/src/controller/field/ReferenceManyFieldController.tsx +++ b/packages/ra-core/src/controller/field/ReferenceManyFieldController.tsx @@ -1,4 +1,4 @@ -import { ReactElement, FunctionComponent } from 'react'; +import { ReactElement } from 'react'; import { Record, SortPayload } from '../../types'; import useReferenceManyFieldController from './useReferenceManyFieldController'; @@ -24,7 +24,7 @@ interface Props { * * @see useReferenceManyFieldController */ -export const ReferenceManyFieldController: FunctionComponent = props => { +export const ReferenceManyFieldController = (props: Props) => { const { children, page = 1, perPage = 25, ...rest } = props; const controllerProps = useReferenceManyFieldController({ page, diff --git a/packages/ra-core/src/controller/input/ReferenceInputController.tsx b/packages/ra-core/src/controller/input/ReferenceInputController.tsx index 5f78e31ff41..be0a20eece6 100644 --- a/packages/ra-core/src/controller/input/ReferenceInputController.tsx +++ b/packages/ra-core/src/controller/input/ReferenceInputController.tsx @@ -1,9 +1,4 @@ -import { - ReactNode, - ComponentType, - FunctionComponent, - ReactElement, -} from 'react'; +import { ReactNode, ComponentType, ReactElement } from 'react'; import { SortPayload, Record } from '../../types'; import { @@ -33,11 +28,9 @@ interface Props { * * @see useReferenceInputController */ -export const ReferenceInputController: FunctionComponent = ({ - children, - ...props -}) => { - return children(useReferenceInputController(props)) as ReactElement; +export const ReferenceInputController = (props: Props) => { + const { children, ...rest } = props; + return children(useReferenceInputController(rest)) as ReactElement; }; export default ReferenceInputController as ComponentType; diff --git a/packages/ra-core/src/core/CoreAdmin.tsx b/packages/ra-core/src/core/CoreAdmin.tsx index fad2fdcd039..9db3248fa57 100644 --- a/packages/ra-core/src/core/CoreAdmin.tsx +++ b/packages/ra-core/src/core/CoreAdmin.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { FunctionComponent, ComponentType } from 'react'; +import { ComponentType } from 'react'; import CoreAdminContext from './CoreAdminContext'; import CoreAdminUI from './CoreAdminUI'; @@ -86,28 +86,29 @@ export type ChildrenFunction = () => ComponentType[]; * ); * }; */ -const CoreAdmin: FunctionComponent = ({ - appLayout, - authProvider, - catchAll, - children, - customReducers, - customRoutes = [], - customSagas, - dashboard, - dataProvider, - disableTelemetry, - history, - i18nProvider, - initialState, - layout, - loading, - loginPage, - logoutButton, - menu, // deprecated, use a custom layout instead - theme, - title = 'React Admin', -}) => { +const CoreAdmin = (props: AdminProps) => { + const { + appLayout, + authProvider, + catchAll, + children, + customReducers, + customRoutes = [], + customSagas, + dashboard, + dataProvider, + disableTelemetry, + history, + i18nProvider, + initialState, + layout, + loading, + loginPage, + logoutButton, + menu, // deprecated, use a custom layout instead + theme, + title = 'React Admin', + } = props; return ( = ({ - authProvider, - dataProvider, - i18nProvider, - children, - history, - customReducers, - customSagas, - initialState, -}) => { +const CoreAdminContext = (props: AdminContextProps) => { + const { + authProvider, + dataProvider, + i18nProvider, + children, + history, + customReducers, + customSagas, + initialState, + } = props; const reduxIsAlreadyInitialized = !!useContext(ReactReduxContext); if (!dataProvider) { diff --git a/packages/ra-core/src/core/CoreAdminRouter.tsx b/packages/ra-core/src/core/CoreAdminRouter.tsx index 11396c5b561..5128ee278d8 100644 --- a/packages/ra-core/src/core/CoreAdminRouter.tsx +++ b/packages/ra-core/src/core/CoreAdminRouter.tsx @@ -5,7 +5,6 @@ import React, { createElement, ComponentType, ReactElement, - FunctionComponent, } from 'react'; import { Route, Switch } from 'react-router-dom'; @@ -36,7 +35,7 @@ export interface AdminRouterProps extends CoreLayoutProps { type State = ResourceElement[]; -const CoreAdminRouter: FunctionComponent = props => { +const CoreAdminRouter = (props: AdminRouterProps) => { const getPermissions = useGetPermissions(); const doLogout = useLogout(); const { authenticated } = useAuthState(); diff --git a/packages/ra-core/src/core/CoreAdminUI.tsx b/packages/ra-core/src/core/CoreAdminUI.tsx index cc0ac8e4dde..cef6b527e96 100644 --- a/packages/ra-core/src/core/CoreAdminUI.tsx +++ b/packages/ra-core/src/core/CoreAdminUI.tsx @@ -1,11 +1,5 @@ import * as React from 'react'; -import { - createElement, - FunctionComponent, - ComponentType, - useMemo, - useEffect, -} from 'react'; +import { createElement, ComponentType, useMemo, useEffect } from 'react'; import { Switch, Route } from 'react-router-dom'; import CoreAdminRouter from './CoreAdminRouter'; @@ -24,9 +18,7 @@ import { export type ChildrenFunction = () => ComponentType[]; -const DefaultLayout: FunctionComponent = ({ children }) => ( - <>{children} -); +const DefaultLayout = ({ children }: CoreLayoutProps) => <>{children}; export interface AdminUIProps { catchAll?: CatchAllComponent; @@ -47,21 +39,23 @@ export interface AdminUIProps { // for BC export type CoreAdminUIProps = AdminUIProps; -const CoreAdminUI: FunctionComponent = ({ - catchAll = Noop, - children, - customRoutes = [], - dashboard, - disableTelemetry = false, - layout = DefaultLayout, - loading = Noop, - loginPage = false, - logout, - menu, // deprecated, use a custom layout instead - ready = Ready, - theme, - title = 'React Admin', -}) => { +const CoreAdminUI = (props: AdminUIProps) => { + const { + catchAll = Noop, + children, + customRoutes = [], + dashboard, + disableTelemetry = false, + layout = DefaultLayout, + loading = Noop, + loginPage = false, + logout, + menu, // deprecated, use a custom layout instead + ready = Ready, + theme, + title = 'React Admin', + } = props; + const logoutElement = useMemo(() => logout && createElement(logout), [ logout, ]); diff --git a/packages/ra-core/src/core/Resource.tsx b/packages/ra-core/src/core/Resource.tsx index 53ddf362c37..c67f2401d6f 100644 --- a/packages/ra-core/src/core/Resource.tsx +++ b/packages/ra-core/src/core/Resource.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { FunctionComponent, useEffect, useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Route, Switch } from 'react-router-dom'; @@ -10,15 +10,16 @@ import { ResourceContextProvider } from './ResourceContextProvider'; const defaultOptions = {}; -const ResourceRegister: FunctionComponent = ({ - name, - list, - create, - edit, - show, - icon, - options = defaultOptions, -}) => { +const ResourceRegister = (props: ResourceProps) => { + const { + name, + list, + create, + edit, + show, + icon, + options = defaultOptions, + } = props; const dispatch = useDispatch(); useEffect(() => { dispatch( @@ -37,15 +38,16 @@ const ResourceRegister: FunctionComponent = ({ return null; }; -const ResourceRoutes: FunctionComponent = ({ - name, - match, - list, - create, - edit, - show, - options = defaultOptions, -}) => { +const ResourceRoutes = (props: ResourceProps) => { + const { + name, + match, + list, + create, + edit, + show, + options = defaultOptions, + } = props; const isRegistered = useSelector( (state: ReduxState) => !!state.admin.resources[name] ); @@ -141,14 +143,13 @@ const ResourceRoutes: FunctionComponent = ({ }, [basePath, name, create, edit, list, show, options, isRegistered]); // eslint-disable-line react-hooks/exhaustive-deps }; -const Resource: FunctionComponent = ({ - intent = 'route', - ...props -}) => - intent === 'registration' ? ( - +const Resource = (props: ResourceProps) => { + const { intent = 'route', ...rest } = props; + return intent === 'registration' ? ( + ) : ( - + ); +}; export default Resource; diff --git a/packages/ra-core/src/core/RoutesWithLayout.tsx b/packages/ra-core/src/core/RoutesWithLayout.tsx index 6a340cff05a..495a41a8100 100644 --- a/packages/ra-core/src/core/RoutesWithLayout.tsx +++ b/packages/ra-core/src/core/RoutesWithLayout.tsx @@ -1,9 +1,4 @@ -import React, { - Children, - cloneElement, - createElement, - FunctionComponent, -} from 'react'; +import React, { Children, cloneElement, createElement } from 'react'; import { Redirect, Route, Switch } from 'react-router-dom'; import WithPermissions from '../auth/WithPermissions'; @@ -25,13 +20,8 @@ interface Props { const defaultAuthParams = { route: 'dashboard' }; -const RoutesWithLayout: FunctionComponent = ({ - catchAll, - children, - customRoutes, - dashboard, - title, -}) => { +const RoutesWithLayout = (props: Props) => { + const { catchAll, children, customRoutes, dashboard, title } = props; const childrenAsArray = React.Children.toArray(children); const firstChild: React.ReactElement | null = childrenAsArray.length > 0 diff --git a/packages/ra-core/src/dataProvider/Mutation.tsx b/packages/ra-core/src/dataProvider/Mutation.tsx index dd0f749278a..71447bcea98 100644 --- a/packages/ra-core/src/dataProvider/Mutation.tsx +++ b/packages/ra-core/src/dataProvider/Mutation.tsx @@ -1,5 +1,3 @@ -import { FunctionComponent } from 'react'; - import useMutation from './useMutation'; interface ChildrenFuncParams { @@ -53,7 +51,7 @@ interface Props { * * ); */ -const Mutation: FunctionComponent = ({ +const Mutation = ({ children, type, resource, @@ -61,7 +59,7 @@ const Mutation: FunctionComponent = ({ // Provides an undefined onSuccess just so the key `onSuccess` is defined // This is used to detect options in useDataProvider options = { onSuccess: undefined }, -}) => +}: Props) => children( ...useMutation( { type, resource, payload }, diff --git a/packages/ra-core/src/form/FormDataConsumer.tsx b/packages/ra-core/src/form/FormDataConsumer.tsx index 41be0b4d636..08d9fce4a02 100644 --- a/packages/ra-core/src/form/FormDataConsumer.tsx +++ b/packages/ra-core/src/form/FormDataConsumer.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { ReactNode, FunctionComponent } from 'react'; +import { ReactNode } from 'react'; import { useFormState } from 'react-final-form'; import { FormSubscription } from 'final-form'; import get from 'lodash/get'; @@ -74,14 +74,8 @@ const FormDataConsumer = ({ subscription, ...props }: ConnectedProps) => { return ; }; -export const FormDataConsumerView: FunctionComponent = ({ - children, - form, - formData, - source, - index, - ...rest -}) => { +export const FormDataConsumerView = (props: Props) => { + const { children, form, formData, source, index, ...rest } = props; let scopedFormData = formData; let getSource; let getSourceHasBeenCalled = false; diff --git a/packages/ra-core/src/form/FormField.tsx b/packages/ra-core/src/form/FormField.tsx index 17db228b9d9..1553785cbee 100644 --- a/packages/ra-core/src/form/FormField.tsx +++ b/packages/ra-core/src/form/FormField.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { FunctionComponent } from 'react'; import PropTypes from 'prop-types'; import { Field, FieldProps, FieldRenderProps } from 'react-final-form'; import { Validator, composeValidators } from './validate'; @@ -25,12 +24,8 @@ interface Props validate?: Validator | Validator[]; } -const FormField: FunctionComponent = ({ - id, - input, - validate, - ...props -}) => { +const FormField = (props: Props) => { + const { id, input, validate, ...rest } = props; if (process.env.NODE_ENV !== 'production') { console.log('FormField is deprecated, use the useInput hook instead.'); } @@ -39,15 +34,15 @@ const FormField: FunctionComponent = ({ ? composeValidators(validate) : validate; - const finalId = id || props.source; + const finalId = id || rest.source; return input ? ( // An ancestor is already decorated by Field - React.createElement(props.component, { input, id: finalId, ...props }) + React.createElement(rest.component, { input, id: finalId, ...rest }) ) : ( diff --git a/packages/ra-core/src/form/ValidationError.tsx b/packages/ra-core/src/form/ValidationError.tsx index 55338593385..cd4f94471c2 100644 --- a/packages/ra-core/src/form/ValidationError.tsx +++ b/packages/ra-core/src/form/ValidationError.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { FunctionComponent } from 'react'; import { ValidationErrorMessage, ValidationErrorMessageWithArgs, @@ -10,7 +9,8 @@ interface Props { error: ValidationErrorMessage; } -const ValidationError: FunctionComponent = ({ error }) => { +const ValidationError = (props: Props) => { + const { error } = props; const translate = useTranslate(); if ((error as ValidationErrorMessageWithArgs).message) { const { message, args } = error as ValidationErrorMessageWithArgs; diff --git a/packages/ra-core/src/i18n/TranslationProvider.tsx b/packages/ra-core/src/i18n/TranslationProvider.tsx index 5dda2c69499..ecabb156185 100644 --- a/packages/ra-core/src/i18n/TranslationProvider.tsx +++ b/packages/ra-core/src/i18n/TranslationProvider.tsx @@ -1,9 +1,4 @@ -import React, { - useCallback, - useMemo, - Children, - FunctionComponent, -} from 'react'; +import React, { useCallback, useMemo, Children, ReactNode } from 'react'; import { useSafeSetState } from '../util/hooks'; import { TranslationContext } from './TranslationContext'; @@ -12,6 +7,7 @@ import { I18nProvider } from '../types'; interface Props { locale?: string; i18nProvider: I18nProvider; + children: ReactNode; } interface State { @@ -31,7 +27,7 @@ interface State { * * ); */ -const TranslationProvider: FunctionComponent = props => { +const TranslationProvider = (props: Props) => { const { i18nProvider, children } = props; const [state, setState] = useSafeSetState({ diff --git a/packages/ra-core/src/util/FieldTitle.tsx b/packages/ra-core/src/util/FieldTitle.tsx index 8467a07183d..36ccd063cb6 100644 --- a/packages/ra-core/src/util/FieldTitle.tsx +++ b/packages/ra-core/src/util/FieldTitle.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { FunctionComponent, ReactElement, memo } from 'react'; +import { ReactElement, memo } from 'react'; import useTranslate from '../i18n/useTranslate'; import getFieldLabelTranslationArgs from './getFieldLabelTranslationArgs'; @@ -11,12 +11,8 @@ interface Props { label?: string | ReactElement | false; } -export const FieldTitle: FunctionComponent = ({ - resource, - source, - label, - isRequired, -}) => { +export const FieldTitle = (props: Props) => { + const { resource, source, label, isRequired } = props; const translate = useTranslate(); if (label === false || label === '') { diff --git a/packages/react-admin/src/Admin.tsx b/packages/react-admin/src/Admin.tsx index 5d613cb8e7b..e7a5a8eb0b7 100644 --- a/packages/react-admin/src/Admin.tsx +++ b/packages/react-admin/src/Admin.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { FunctionComponent } from 'react'; import { AdminProps } from 'ra-core'; import AdminContext from './AdminContext'; @@ -84,30 +83,32 @@ import { useEffect, useState } from 'react'; * ); * }; */ -const Admin: FunctionComponent = ({ - appLayout, - authProvider, - catchAll, - children, - customReducers, - customRoutes = [], - customSagas, - dashboard, - dataProvider, - disableTelemetry, - history, - i18nProvider, - initialState, - layout, - loading, - locale, - loginPage, - logoutButton, - menu, // deprecated, use a custom layout instead - ready, - theme, - title = 'React Admin', -}) => { +const Admin = (props: AdminProps) => { + const { + appLayout, + authProvider, + catchAll, + children, + customReducers, + customRoutes = [], + customSagas, + dashboard, + dataProvider, + disableTelemetry, + history, + i18nProvider, + initialState, + layout, + loading, + locale, + loginPage, + logoutButton, + menu, // deprecated, use a custom layout instead + ready, + theme, + title = 'React Admin', + } = props; + if (appLayout && process.env.NODE_ENV !== 'production') { console.warn( 'You are using deprecated prop "appLayout", it was replaced by "layout", see https://github.com/marmelab/react-admin/issues/2918' diff --git a/packages/react-admin/src/AdminRouter.tsx b/packages/react-admin/src/AdminRouter.tsx index f4e229c6427..d3fe84bb675 100644 --- a/packages/react-admin/src/AdminRouter.tsx +++ b/packages/react-admin/src/AdminRouter.tsx @@ -1,11 +1,8 @@ import * as React from 'react'; -import { FC } from 'react'; import { CoreAdminRouter, AdminRouterProps } from 'ra-core'; import { LoadingPage } from 'ra-ui-materialui'; -const AdminRouter: FC = props => ( - -); +const AdminRouter = (props: AdminRouterProps) => ; AdminRouter.defaultProps = { loading: LoadingPage,