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:
@@ -58,7 +58,7 @@ import alertService from '@/services/alerts/alertService';
|
|||||||
|
|
||||||
interface ITaskAssignee {
|
interface ITaskAssignee {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
avatar_url?: string;
|
avatar_url?: string;
|
||||||
team_member_id: string;
|
team_member_id: string;
|
||||||
@@ -437,7 +437,7 @@ const TaskListBulkActionsBar = () => {
|
|||||||
placement="top"
|
placement="top"
|
||||||
arrow
|
arrow
|
||||||
trigger={['click']}
|
trigger={['click']}
|
||||||
destroyPopupOnHide
|
destroyOnHidden
|
||||||
onOpenChange={value => {
|
onOpenChange={value => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
setSelectedLabels([]);
|
setSelectedLabels([]);
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ const TimerButton = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownRender={() => dropdownContent}
|
popupRender={() => dropdownContent}
|
||||||
trigger={['click']}
|
trigger={['click']}
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
open={dropdownOpen}
|
open={dropdownOpen}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ import { IProjectTask } from '@/types/project/projectTasksViewModel.types';
|
|||||||
|
|
||||||
export const useTaskDragAndDrop = () => {
|
export const useTaskDragAndDrop = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { taskGroups, groupBy } = useAppSelector(state => ({
|
|
||||||
taskGroups: state.taskReducer.taskGroups,
|
// Memoize the selector to prevent unnecessary rerenders
|
||||||
groupBy: state.taskReducer.groupBy,
|
const taskGroups = useAppSelector(state => state.taskReducer.taskGroups);
|
||||||
}));
|
const groupBy = useAppSelector(state => state.taskReducer.groupBy);
|
||||||
|
|
||||||
// Memoize sensors configuration for better performance
|
// Memoize sensors configuration for better performance
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ const ProjectView = () => {
|
|||||||
onChange={handleTabChange}
|
onChange={handleTabChange}
|
||||||
items={tabMenuItems}
|
items={tabMenuItems}
|
||||||
tabBarStyle={{ paddingInline: 0 }}
|
tabBarStyle={{ paddingInline: 0 }}
|
||||||
destroyInactiveTabPane={true}
|
destroyOnHidden={true}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{portalElements}
|
{portalElements}
|
||||||
|
|||||||
@@ -19,36 +19,19 @@ const ProjectViewTaskList = () => {
|
|||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
|
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
|
||||||
|
|
||||||
// Combine related selectors to reduce subscriptions
|
// Split selectors to prevent unnecessary rerenders
|
||||||
const {
|
const projectId = useAppSelector(state => state.projectReducer.projectId);
|
||||||
projectId,
|
const taskGroups = useAppSelector(state => state.taskReducer.taskGroups);
|
||||||
taskGroups,
|
const loadingGroups = useAppSelector(state => state.taskReducer.loadingGroups);
|
||||||
loadingGroups,
|
const groupBy = useAppSelector(state => state.taskReducer.groupBy);
|
||||||
groupBy,
|
const archived = useAppSelector(state => state.taskReducer.archived);
|
||||||
archived,
|
const fields = useAppSelector(state => state.taskReducer.fields);
|
||||||
fields,
|
const search = useAppSelector(state => state.taskReducer.search);
|
||||||
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,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const {
|
const statusCategories = useAppSelector(state => state.taskStatusReducer.statusCategories);
|
||||||
statusCategories,
|
const loadingStatusCategories = useAppSelector(state => state.taskStatusReducer.loading);
|
||||||
loading: loadingStatusCategories,
|
|
||||||
} = useAppSelector(state => ({
|
|
||||||
statusCategories: state.taskStatusReducer.statusCategories,
|
|
||||||
loading: state.taskStatusReducer.loading,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const { loadingPhases } = useAppSelector(state => ({
|
const loadingPhases = useAppSelector(state => state.phaseReducer.loadingPhases);
|
||||||
loadingPhases: state.phaseReducer.loadingPhases,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Single source of truth for loading state - EXCLUDE labels loading from skeleton
|
// Single source of truth for loading state - EXCLUDE labels loading from skeleton
|
||||||
// Labels loading should not block the main task list display
|
// Labels loading should not block the main task list display
|
||||||
|
|||||||
Reference in New Issue
Block a user