mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-30 06:11:38 +00:00
removal of multiple useMemo & useCallbacks to reduce the over optimization
This commit is contained in:
@@ -74,7 +74,6 @@ export const getCopyJobs = async (): Promise<CopyJobType[]> => {
|
||||
}
|
||||
copyJobsAbortController = null;
|
||||
|
||||
/* added a lower bound to "0" and upper bound to "100" */
|
||||
const calculateCompletionPercentage = (processed: number, total: number): number => {
|
||||
if (
|
||||
typeof processed !== "number" ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DatabaseAccount } from "Contracts/DataModels";
|
||||
import { CopyJobErrorType } from "./Types/CopyJobTypes";
|
||||
import { CopyJobErrorType, CopyJobType } from "./Types/CopyJobTypes";
|
||||
|
||||
const azurePortalMpacEndpoint = "https://ms.portal.azure.com/";
|
||||
|
||||
@@ -124,3 +124,15 @@ export function isIntraAccountCopy(sourceAccountId: string | undefined, targetAc
|
||||
sourceAccountDetails?.accountName === targetAccountDetails?.accountName
|
||||
);
|
||||
}
|
||||
export function isEqual(prevJobs: CopyJobType[], newJobs: CopyJobType[]): boolean {
|
||||
if (prevJobs.length !== newJobs.length) {
|
||||
return false;
|
||||
}
|
||||
return prevJobs.every((prevJob: CopyJobType) => {
|
||||
const newJob = newJobs.find((job) => job.Name === prevJob.Name);
|
||||
if (!newJob) {
|
||||
return false;
|
||||
}
|
||||
return prevJob.Status === newJob.Status;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Link, Stack, Text, Toggle } from "@fluentui/react";
|
||||
import React, { useCallback } from "react";
|
||||
import React from "react";
|
||||
import { logError } from "../../../../../Common/Logger";
|
||||
import { assignRole } from "../../../../../Utils/arm/RbacUtils";
|
||||
import ContainerCopyMessages from "../../../ContainerCopyMessages";
|
||||
@@ -25,7 +25,7 @@ const AddReadPermissionToDefaultIdentity: React.FC<AddReadPermissionToDefaultIde
|
||||
const { copyJobState, setCopyJobState, setContextError } = useCopyJobContext();
|
||||
const [readPermissionAssigned, onToggle] = useToggle(false);
|
||||
|
||||
const handleAddReadPermission = useCallback(async () => {
|
||||
const handleAddReadPermission = async () => {
|
||||
const { source, target } = copyJobState;
|
||||
const selectedSourceAccount = source?.account;
|
||||
try {
|
||||
@@ -56,7 +56,7 @@ const AddReadPermissionToDefaultIdentity: React.FC<AddReadPermissionToDefaultIde
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [copyJobState, setCopyJobState, setContextError]);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack className="defaultManagedIdentityContainer" tokens={{ childrenGap: 15, padding: "0 0 0 20px" }}>
|
||||
|
||||
@@ -47,7 +47,7 @@ const useManagedIdentity = (
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [copyJobState, updateIdentityFn, setCopyJobState]);
|
||||
}, [updateIdentityFn]);
|
||||
|
||||
return { loading, handleAddSystemIdentity };
|
||||
};
|
||||
|
||||
@@ -26,5 +26,5 @@ export const AccountDropdown: React.FC<AccountDropdownProps> = React.memo(
|
||||
onChange={onChange}
|
||||
/>
|
||||
</FieldRow>
|
||||
),
|
||||
), (prev, next) => prev.options.length === next.options.length
|
||||
);
|
||||
|
||||
@@ -24,5 +24,5 @@ export const SubscriptionDropdown: React.FC<SubscriptionDropdownProps> = React.m
|
||||
onChange={onChange}
|
||||
/>
|
||||
</FieldRow>
|
||||
),
|
||||
), (prev, next) => prev.options.length === next.options.length
|
||||
);
|
||||
|
||||
@@ -11,25 +11,17 @@ export function useDropdownOptions(
|
||||
subscriptionOptions: DropdownOptionType[];
|
||||
accountOptions: DropdownOptionType[];
|
||||
} {
|
||||
const subscriptionOptions = React.useMemo(
|
||||
() =>
|
||||
subscriptions?.map((sub) => ({
|
||||
key: sub.subscriptionId,
|
||||
text: sub.displayName,
|
||||
data: sub,
|
||||
})) || [],
|
||||
[subscriptions],
|
||||
);
|
||||
const subscriptionOptions = subscriptions?.map((sub) => ({
|
||||
key: sub.subscriptionId,
|
||||
text: sub.displayName,
|
||||
data: sub,
|
||||
})) || [];
|
||||
|
||||
const accountOptions = React.useMemo(
|
||||
() =>
|
||||
accounts?.map((account) => ({
|
||||
key: account.id,
|
||||
text: account.name,
|
||||
data: account,
|
||||
})) || [],
|
||||
[accounts],
|
||||
);
|
||||
const accountOptions = accounts?.map((account) => ({
|
||||
key: account.id,
|
||||
text: account.name,
|
||||
data: account,
|
||||
})) || [];
|
||||
|
||||
return { subscriptionOptions, accountOptions };
|
||||
}
|
||||
@@ -38,8 +30,7 @@ type setCopyJobStateType = CopyJobContextProviderType["setCopyJobState"];
|
||||
|
||||
export function useEventHandlers(setCopyJobState: setCopyJobStateType) {
|
||||
const { setValidationCache } = useCopyJobPrerequisitesCache();
|
||||
const handleSelectSourceAccount = React.useCallback(
|
||||
(type: "subscription" | "account", data: (Subscription & DatabaseAccount) | undefined) => {
|
||||
const handleSelectSourceAccount = (type: "subscription" | "account", data: (Subscription & DatabaseAccount) | undefined) => {
|
||||
setCopyJobState((prevState: CopyJobContextState) => {
|
||||
if (type === "subscription") {
|
||||
return {
|
||||
@@ -63,9 +54,7 @@ export function useEventHandlers(setCopyJobState: setCopyJobStateType) {
|
||||
return prevState;
|
||||
});
|
||||
setValidationCache(new Map<string, boolean>());
|
||||
},
|
||||
[setCopyJobState, setValidationCache],
|
||||
);
|
||||
};
|
||||
|
||||
const handleMigrationTypeChange = React.useCallback(
|
||||
(_ev?: React.FormEvent<HTMLElement>, checked?: boolean) => {
|
||||
@@ -75,7 +64,7 @@ export function useEventHandlers(setCopyJobState: setCopyJobStateType) {
|
||||
}));
|
||||
setValidationCache(new Map<string, boolean>());
|
||||
},
|
||||
[setCopyJobState, setValidationCache],
|
||||
[],
|
||||
);
|
||||
|
||||
return { handleSelectSourceAccount, handleMigrationTypeChange };
|
||||
|
||||
@@ -7,36 +7,40 @@ import ContainerCopyMessages from "../../../ContainerCopyMessages";
|
||||
import { useCopyJobContext } from "../../../Context/CopyJobContext";
|
||||
import { DatabaseContainerSection } from "./components/DatabaseContainerSection";
|
||||
import { dropDownChangeHandler } from "./Events/DropDownChangeHandler";
|
||||
import { useMemoizedSourceAndTargetData } from "./memoizedData";
|
||||
import { useSourceAndTargetData } from "./memoizedData";
|
||||
|
||||
const SelectSourceAndTargetContainers = () => {
|
||||
const { copyJobState, setCopyJobState } = useCopyJobContext();
|
||||
const { source, target, sourceDbParams, sourceContainerParams, targetDbParams, targetContainerParams } =
|
||||
useMemoizedSourceAndTargetData(copyJobState);
|
||||
useSourceAndTargetData(copyJobState);
|
||||
|
||||
const sourceDatabases = useDatabases(...sourceDbParams) || [];
|
||||
const sourceContainers = useDataContainers(...sourceContainerParams) || [];
|
||||
const targetDatabases = useDatabases(...targetDbParams) || [];
|
||||
const targetContainers = useDataContainers(...targetContainerParams) || [];
|
||||
if(!source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sourceDatabases = useDatabases(...sourceDbParams);
|
||||
const sourceContainers = useDataContainers(...sourceContainerParams);
|
||||
const targetDatabases = useDatabases(...targetDbParams);
|
||||
const targetContainers = useDataContainers(...targetContainerParams);
|
||||
|
||||
const sourceDatabaseOptions = React.useMemo(
|
||||
() => sourceDatabases.map((db: DatabaseModel) => ({ key: db.name, text: db.name, data: db })),
|
||||
() => sourceDatabases?.map((db: DatabaseModel) => ({ key: db.name, text: db.name, data: db })) || [],
|
||||
[sourceDatabases],
|
||||
);
|
||||
const sourceContainerOptions = React.useMemo(
|
||||
() => sourceContainers.map((c: DatabaseModel) => ({ key: c.name, text: c.name, data: c })),
|
||||
() => sourceContainers?.map((c: DatabaseModel) => ({ key: c.name, text: c.name, data: c })) || [],
|
||||
[sourceContainers],
|
||||
);
|
||||
const targetDatabaseOptions = React.useMemo(
|
||||
() => targetDatabases.map((db: DatabaseModel) => ({ key: db.name, text: db.name, data: db })),
|
||||
() => targetDatabases?.map((db: DatabaseModel) => ({ key: db.name, text: db.name, data: db })) || [],
|
||||
[targetDatabases],
|
||||
);
|
||||
const targetContainerOptions = React.useMemo(
|
||||
() => targetContainers.map((c: DatabaseModel) => ({ key: c.name, text: c.name, data: c })),
|
||||
() => targetContainers?.map((c: DatabaseModel) => ({ key: c.name, text: c.name, data: c })) || [],
|
||||
[targetContainers],
|
||||
);
|
||||
|
||||
const onDropdownChange = React.useCallback(dropDownChangeHandler(setCopyJobState), [setCopyJobState]);
|
||||
const onDropdownChange = dropDownChangeHandler(setCopyJobState);
|
||||
|
||||
return (
|
||||
<Stack className="selectSourceAndTargetContainers" tokens={{ childrenGap: 25 }}>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from "react";
|
||||
import { getAccountDetailsFromResourceId } from "../../../CopyJobUtils";
|
||||
import { CopyJobContextState, DatabaseParams, DataContainerParams } from "../../../Types/CopyJobTypes";
|
||||
|
||||
export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState) {
|
||||
export function useSourceAndTargetData(copyJobState: CopyJobContextState) {
|
||||
const { source, target } = copyJobState ?? {};
|
||||
const selectedSourceAccount = source?.account;
|
||||
const selectedTargetAccount = target?.account;
|
||||
@@ -17,27 +16,10 @@ export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState
|
||||
accountName: targetAccountName,
|
||||
} = getAccountDetailsFromResourceId(selectedTargetAccount?.id);
|
||||
|
||||
const sourceDbParams = React.useMemo(
|
||||
() => [sourceSubscriptionId, sourceResourceGroup, sourceAccountName, "SQL"] as DatabaseParams,
|
||||
[sourceSubscriptionId, sourceResourceGroup, sourceAccountName],
|
||||
);
|
||||
|
||||
const sourceContainerParams = React.useMemo(
|
||||
() =>
|
||||
[sourceSubscriptionId, sourceResourceGroup, sourceAccountName, source?.databaseId, "SQL"] as DataContainerParams,
|
||||
[sourceSubscriptionId, sourceResourceGroup, sourceAccountName, source?.databaseId],
|
||||
);
|
||||
|
||||
const targetDbParams = React.useMemo(
|
||||
() => [targetSubscriptionId, targetResourceGroup, targetAccountName, "SQL"] as DatabaseParams,
|
||||
[targetSubscriptionId, targetResourceGroup, targetAccountName],
|
||||
);
|
||||
|
||||
const targetContainerParams = React.useMemo(
|
||||
() =>
|
||||
[targetSubscriptionId, targetResourceGroup, targetAccountName, target?.databaseId, "SQL"] as DataContainerParams,
|
||||
[targetSubscriptionId, targetResourceGroup, targetAccountName, target?.databaseId],
|
||||
);
|
||||
const sourceDbParams = [sourceSubscriptionId, sourceResourceGroup, sourceAccountName, "SQL"] as DatabaseParams;
|
||||
const sourceContainerParams = [sourceSubscriptionId, sourceResourceGroup, sourceAccountName, source?.databaseId, "SQL"] as DataContainerParams;
|
||||
const targetDbParams = [targetSubscriptionId, targetResourceGroup, targetAccountName, "SQL"] as DatabaseParams;
|
||||
const targetContainerParams = [targetSubscriptionId, targetResourceGroup, targetAccountName, target?.databaseId, "SQL"] as DataContainerParams;
|
||||
|
||||
return { source, target, sourceDbParams, sourceContainerParams, targetDbParams, targetContainerParams };
|
||||
}
|
||||
|
||||
@@ -85,3 +85,4 @@ function useCreateCopyJobScreensList() {
|
||||
}
|
||||
|
||||
export { SCREEN_KEYS, useCreateCopyJobScreensList };
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const iconMap: Partial<Record<CopyJobStatusType, string>> = {
|
||||
[CopyJobStatusType.Completed]: "CompletedSolid",
|
||||
};
|
||||
|
||||
const CopyJobStatusWithIcon: React.FC<{ status: CopyJobStatusType }> = ({ status }) => {
|
||||
const CopyJobStatusWithIcon: React.FC<{ status: CopyJobStatusType }> = React.memo(({ status }) => {
|
||||
const statusText = ContainerCopyMessages.MonitorJobs.Status[status] || "Unknown";
|
||||
|
||||
const isSpinnerStatus = [
|
||||
@@ -57,6 +57,6 @@ const CopyJobStatusWithIcon: React.FC<{ status: CopyJobStatusType }> = ({ status
|
||||
<Text>{statusText}</Text>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default CopyJobStatusWithIcon;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ActionButton, Image } from "@fluentui/react";
|
||||
import React, { useCallback } from "react";
|
||||
import React, { memo } from "react";
|
||||
import CopyJobIcon from "../../../../../images/ContainerCopy/copy-jobs.svg";
|
||||
import * as Actions from "../../Actions/CopyJobActions";
|
||||
import ContainerCopyMessages from "../../ContainerCopyMessages";
|
||||
@@ -7,16 +7,15 @@ import ContainerCopyMessages from "../../ContainerCopyMessages";
|
||||
interface CopyJobsNotFoundProps {}
|
||||
|
||||
const CopyJobsNotFound: React.FC<CopyJobsNotFoundProps> = () => {
|
||||
const handleCreateCopyJob = useCallback(Actions.openCreateCopyJobPanel, []);
|
||||
return (
|
||||
<div className="notFoundContainer flexContainer centerContent">
|
||||
<Image src={CopyJobIcon} alt={ContainerCopyMessages.noCopyJobsTitle} width={100} height={100} />
|
||||
<h4 className="noCopyJobsMessage">{ContainerCopyMessages.noCopyJobsTitle}</h4>
|
||||
<ActionButton allowDisabledFocus className="createCopyJobButton" onClick={handleCreateCopyJob}>
|
||||
<ActionButton allowDisabledFocus className="createCopyJobButton" onClick={Actions.openCreateCopyJobPanel}>
|
||||
{ContainerCopyMessages.createCopyJobButtonText}
|
||||
</ActionButton>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CopyJobsNotFound;
|
||||
export default memo(CopyJobsNotFound);
|
||||
|
||||
@@ -58,22 +58,19 @@ const CopyJobsList: React.FC<CopyJobsListProps> = ({ jobs, handleActionClick, pa
|
||||
setStartIndex(0);
|
||||
};
|
||||
|
||||
const columns: IColumn[] = React.useMemo(
|
||||
() => getColumns(handleSort, handleActionClick, sortedColumnKey, isSortedDescending),
|
||||
[handleSort, handleActionClick, sortedColumnKey, isSortedDescending],
|
||||
);
|
||||
const columns: IColumn[] = getColumns(handleSort, handleActionClick, sortedColumnKey, isSortedDescending);
|
||||
|
||||
const _handleRowClick = React.useCallback((job: CopyJobType) => {
|
||||
const _handleRowClick = (job: CopyJobType) => {
|
||||
openCopyJobDetailsPanel(job);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const _onRenderRow = React.useCallback((props: any) => {
|
||||
const _onRenderRow = (props: any) => {
|
||||
return (
|
||||
<div onClick={_handleRowClick.bind(null, props.item)}>
|
||||
<DetailsRow {...props} styles={{ root: { cursor: "pointer" } }} />
|
||||
</div>
|
||||
);
|
||||
}, []);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
|
||||
@@ -3,13 +3,14 @@ import { MessageBar, MessageBarType, Stack } from "@fluentui/react";
|
||||
import ShimmerTree, { IndentLevel } from "Common/ShimmerTree/ShimmerTree";
|
||||
import React, { forwardRef, useEffect, useImperativeHandle } from "react";
|
||||
import { getCopyJobs, updateCopyJobStatus } from "../Actions/CopyJobActions";
|
||||
import { convertToCamelCase } from "../CopyJobUtils";
|
||||
import { convertToCamelCase, isEqual } from "../CopyJobUtils";
|
||||
import { CopyJobStatusType } from "../Enums/CopyJobEnums";
|
||||
import CopyJobsNotFound from "../MonitorCopyJobs/Components/CopyJobs.NotFound";
|
||||
import { CopyJobType, JobActionUpdatorType } from "../Types/CopyJobTypes";
|
||||
import CopyJobsList from "./Components/CopyJobsList";
|
||||
|
||||
const FETCH_INTERVAL_MS = 30 * 1000;
|
||||
const SHIMMER_INDENT_LEVELS: IndentLevel[] = Array(7).fill({ level: 0, width: "100%" });
|
||||
|
||||
interface MonitorCopyJobsProps {}
|
||||
|
||||
@@ -24,8 +25,6 @@ const MonitorCopyJobs = forwardRef<MonitorCopyJobsRef, MonitorCopyJobsProps>((_p
|
||||
const isUpdatingRef = React.useRef(false);
|
||||
const isFirstFetchRef = React.useRef(true);
|
||||
|
||||
const indentLevels = React.useMemo<IndentLevel[]>(() => Array(7).fill({ level: 0, width: "100%" }), []);
|
||||
|
||||
const fetchJobs = React.useCallback(async () => {
|
||||
if (isUpdatingRef.current) {
|
||||
return;
|
||||
@@ -38,8 +37,7 @@ const MonitorCopyJobs = forwardRef<MonitorCopyJobsRef, MonitorCopyJobsProps>((_p
|
||||
|
||||
const response = await getCopyJobs();
|
||||
setJobs((prevJobs) => {
|
||||
const isSame = JSON.stringify(prevJobs) === JSON.stringify(response);
|
||||
return isSame ? prevJobs : response;
|
||||
return isEqual(prevJobs, response) ? prevJobs : response;
|
||||
});
|
||||
} catch (error) {
|
||||
setError(error.message || "Failed to load copy jobs. Please try again later.");
|
||||
@@ -96,7 +94,7 @@ const MonitorCopyJobs = forwardRef<MonitorCopyJobsRef, MonitorCopyJobsProps>((_p
|
||||
[],
|
||||
);
|
||||
|
||||
const memoizedJobsList = React.useMemo(() => {
|
||||
const renderJobsList = () => {
|
||||
if (loading) {
|
||||
return null;
|
||||
}
|
||||
@@ -104,17 +102,17 @@ const MonitorCopyJobs = forwardRef<MonitorCopyJobsRef, MonitorCopyJobsProps>((_p
|
||||
return <CopyJobsList jobs={jobs} handleActionClick={handleActionClick} />;
|
||||
}
|
||||
return <CopyJobsNotFound />;
|
||||
}, [jobs, loading, handleActionClick]);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack className="monitorCopyJobs flexContainer">
|
||||
{loading && <ShimmerTree indentLevels={indentLevels} style={{ width: "100%", padding: "1rem 2.5rem" }} />}
|
||||
{loading && <ShimmerTree indentLevels={SHIMMER_INDENT_LEVELS} style={{ width: "100%", padding: "1rem 2.5rem" }} />}
|
||||
{error && (
|
||||
<MessageBar messageBarType={MessageBarType.error} isMultiline={false} onDismiss={() => setError(null)}>
|
||||
{error}
|
||||
</MessageBar>
|
||||
)}
|
||||
{memoizedJobsList}
|
||||
{renderJobsList()}
|
||||
</Stack>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user