refactor(task-list): optimize selector usage and update component properties

- Changed `name` property in `ITaskAssignee` interface from optional to required for better type safety.
- Updated `Dropdown` component's prop from `dropdownRender` to `popupRender` for consistency.
- Renamed `destroyPopupOnHide` to `destroyOnHidden` in relevant components for clarity.
- Split combined selectors in `ProjectViewTaskList` to prevent unnecessary re-renders, enhancing performance.
This commit is contained in:
chamiakJ
2025-06-05 11:24:07 +05:30
parent bd77733935
commit 6002ab7c50
5 changed files with 19 additions and 36 deletions

View File

@@ -58,7 +58,7 @@ import alertService from '@/services/alerts/alertService';
interface ITaskAssignee {
id: string;
name?: string;
name: string;
email?: string;
avatar_url?: string;
team_member_id: string;
@@ -437,7 +437,7 @@ const TaskListBulkActionsBar = () => {
placement="top"
arrow
trigger={['click']}
destroyPopupOnHide
destroyOnHidden
onOpenChange={value => {
if (!value) {
setSelectedLabels([]);

View File

@@ -241,7 +241,7 @@ const TimerButton = () => {
return (
<Dropdown
dropdownRender={() => dropdownContent}
popupRender={() => dropdownContent}
trigger={['click']}
placement="bottomRight"
open={dropdownOpen}

View File

@@ -19,10 +19,10 @@ import { IProjectTask } from '@/types/project/projectTasksViewModel.types';
export const useTaskDragAndDrop = () => {
const dispatch = useAppDispatch();
const { taskGroups, groupBy } = useAppSelector(state => ({
taskGroups: state.taskReducer.taskGroups,
groupBy: state.taskReducer.groupBy,
}));
// Memoize the selector to prevent unnecessary rerenders
const taskGroups = useAppSelector(state => state.taskReducer.taskGroups);
const groupBy = useAppSelector(state => state.taskReducer.groupBy);
// Memoize sensors configuration for better performance
const sensors = useSensors(

View File

@@ -177,7 +177,7 @@ const ProjectView = () => {
onChange={handleTabChange}
items={tabMenuItems}
tabBarStyle={{ paddingInline: 0 }}
destroyInactiveTabPane={true}
destroyOnHidden={true}
/>
{portalElements}

View File

@@ -19,36 +19,19 @@ const ProjectViewTaskList = () => {
const [searchParams, setSearchParams] = useSearchParams();
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
// Combine related selectors to reduce subscriptions
const {
projectId,
taskGroups,
loadingGroups,
groupBy,
archived,
fields,
search,
} = useAppSelector(state => ({
projectId: state.projectReducer.projectId,
taskGroups: state.taskReducer.taskGroups,
loadingGroups: state.taskReducer.loadingGroups,
groupBy: state.taskReducer.groupBy,
archived: state.taskReducer.archived,
fields: state.taskReducer.fields,
search: state.taskReducer.search,
}));
// Split selectors to prevent unnecessary rerenders
const projectId = useAppSelector(state => state.projectReducer.projectId);
const taskGroups = useAppSelector(state => state.taskReducer.taskGroups);
const loadingGroups = useAppSelector(state => state.taskReducer.loadingGroups);
const groupBy = useAppSelector(state => state.taskReducer.groupBy);
const archived = useAppSelector(state => state.taskReducer.archived);
const fields = useAppSelector(state => state.taskReducer.fields);
const search = useAppSelector(state => state.taskReducer.search);
const {
statusCategories,
loading: loadingStatusCategories,
} = useAppSelector(state => ({
statusCategories: state.taskStatusReducer.statusCategories,
loading: state.taskStatusReducer.loading,
}));
const statusCategories = useAppSelector(state => state.taskStatusReducer.statusCategories);
const loadingStatusCategories = useAppSelector(state => state.taskStatusReducer.loading);
const { loadingPhases } = useAppSelector(state => ({
loadingPhases: state.phaseReducer.loadingPhases,
}));
const loadingPhases = useAppSelector(state => state.phaseReducer.loadingPhases);
// Single source of truth for loading state - EXCLUDE labels loading from skeleton
// Labels loading should not block the main task list display