refactor(project-view): optimize component with useMemo and useCallback for performance improvements

- Introduced useMemo and useCallback to memoize tab menu items and callback functions, enhancing performance.
- Added resetProjectData function to clean up project state on component unmount.
- Refactored the component to use React.memo for preventing unnecessary re-renders.
This commit is contained in:
chamiakJ
2025-05-18 20:15:40 +05:30
parent 49bdd00dac
commit f3a7fd8be5

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useMemo, useCallback } from 'react';
import { PushpinFilled, PushpinOutlined, QuestionCircleOutlined } from '@ant-design/icons'; import { PushpinFilled, PushpinOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Badge, Button, ConfigProvider, Flex, Tabs, TabsProps, Tooltip } from 'antd'; import { Badge, Button, ConfigProvider, Flex, Tabs, TabsProps, Tooltip } from 'antd';
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom';
@@ -43,6 +43,14 @@ const ProjectView = () => {
const [pinnedTab, setPinnedTab] = useState<string>(searchParams.get('pinned_tab') || ''); const [pinnedTab, setPinnedTab] = useState<string>(searchParams.get('pinned_tab') || '');
const [taskid, setTaskId] = useState<string>(searchParams.get('task') || ''); const [taskid, setTaskId] = useState<string>(searchParams.get('task') || '');
const resetProjectData = useCallback(() => {
dispatch(setProjectId(null));
dispatch(resetStatuses());
dispatch(deselectAll());
dispatch(resetTaskListData());
dispatch(resetBoardData());
}, [dispatch]);
useEffect(() => { useEffect(() => {
if (projectId) { if (projectId) {
dispatch(setProjectId(projectId)); dispatch(setProjectId(projectId));
@@ -59,9 +67,13 @@ const ProjectView = () => {
dispatch(setSelectedTaskId(taskid || '')); dispatch(setSelectedTaskId(taskid || ''));
dispatch(setShowTaskDrawer(true)); dispatch(setShowTaskDrawer(true));
} }
}, [dispatch, navigate, projectId, taskid]);
const pinToDefaultTab = async (itemKey: string) => { return () => {
resetProjectData();
};
}, [dispatch, navigate, projectId, taskid, resetProjectData]);
const pinToDefaultTab = useCallback(async (itemKey: string) => {
if (!itemKey || !projectId) return; if (!itemKey || !projectId) return;
const defaultView = itemKey === 'tasks-list' ? 'TASK_LIST' : 'BOARD'; const defaultView = itemKey === 'tasks-list' ? 'TASK_LIST' : 'BOARD';
@@ -88,9 +100,9 @@ const ProjectView = () => {
}).toString(), }).toString(),
}); });
} }
}; }, [projectId, activeTab, navigate]);
const handleTabChange = (key: string) => { const handleTabChange = useCallback((key: string) => {
setActiveTab(key); setActiveTab(key);
dispatch(setProjectView(key === 'board' ? 'kanban' : 'list')); dispatch(setProjectView(key === 'board' ? 'kanban' : 'list'));
navigate({ navigate({
@@ -100,9 +112,9 @@ const ProjectView = () => {
pinned_tab: pinnedTab, pinned_tab: pinnedTab,
}).toString(), }).toString(),
}); });
}; }, [dispatch, location.pathname, navigate, pinnedTab]);
const tabMenuItems = tabItems.map(item => ({ const tabMenuItems = useMemo(() => tabItems.map(item => ({
key: item.key, key: item.key,
label: ( label: (
<Flex align="center" style={{ color: colors.skyBlue }}> <Flex align="center" style={{ color: colors.skyBlue }}>
@@ -144,21 +156,17 @@ const ProjectView = () => {
</Flex> </Flex>
), ),
children: item.element, children: item.element,
})); })), [pinnedTab, pinToDefaultTab]);
const resetProjectData = () => { const portalElements = useMemo(() => (
dispatch(setProjectId(null)); <>
dispatch(resetStatuses()); {createPortal(<ProjectMemberDrawer />, document.body, 'project-member-drawer')}
dispatch(deselectAll()); {createPortal(<PhaseDrawer />, document.body, 'phase-drawer')}
dispatch(resetTaskListData()); {createPortal(<StatusDrawer />, document.body, 'status-drawer')}
dispatch(resetBoardData()); {createPortal(<TaskDrawer />, document.body, 'task-drawer')}
}; {createPortal(<DeleteStatusDrawer />, document.body, 'delete-status-drawer')}
</>
useEffect(() => { ), []);
return () => {
resetProjectData();
};
}, []);
return ( return (
<div style={{ marginBlockStart: 80, marginBlockEnd: 24, minHeight: '80vh' }}> <div style={{ marginBlockStart: 80, marginBlockEnd: 24, minHeight: '80vh' }}>
@@ -170,33 +178,11 @@ const ProjectView = () => {
items={tabMenuItems} items={tabMenuItems}
tabBarStyle={{ paddingInline: 0 }} tabBarStyle={{ paddingInline: 0 }}
destroyInactiveTabPane={true} destroyInactiveTabPane={true}
// tabBarExtraContent={
// <div>
// <span style={{ position: 'relative', top: '-10px' }}>
// <Tooltip title="Members who are active on this project will be displayed here.">
// <QuestionCircleOutlined />
// </Tooltip>
// </span>
// <span
// style={{
// position: 'relative',
// right: '20px',
// top: '10px',
// }}
// >
// <Badge status="success" dot className="profile-badge" />
// </span>
// </div>
// }
/> />
{createPortal(<ProjectMemberDrawer />, document.body, 'project-member-drawer')} {portalElements}
{createPortal(<PhaseDrawer />, document.body, 'phase-drawer')}
{createPortal(<StatusDrawer />, document.body, 'status-drawer')}
{createPortal(<TaskDrawer />, document.body, 'task-drawer')}
{createPortal(<DeleteStatusDrawer />, document.body, 'delete-status-drawer')}
</div> </div>
); );
}; };
export default ProjectView; export default React.memo(ProjectView);