-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Labels
refactorCode refactoringCode refactoring
Description
Problem
The isMountedRef pattern is duplicated across 4+ sheet components to prevent state updates on unmounted components.
Duplicated Pattern
const isMountedRef = useRef(true);
useEffect(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);Affected Files
components/sheets/LogSlipUpSheet.tsx(lines 136-142)components/sheets/TaskCompletionSheet.tsx(lines 115-121)components/sheets/EditDisplayNameSheet.tsx(lines 136-142)components/TaskCreationSheet.tsx(lines 115-123)
Proposed Solution
Create a reusable custom hook in hooks/useMounted.ts:
import { useRef, useEffect } from 'react';
/**
* Hook to track component mount state.
* Useful for preventing state updates after unmount in async operations.
*
* @returns Ref that is true while component is mounted, false after unmount
* @example
* const isMounted = useMounted();
*
* async function fetchData() {
* const result = await api.fetch();
* if (isMounted.current) {
* setData(result);
* }
* }
*/
export function useMounted(): React.MutableRefObject<boolean> {
const isMountedRef = useRef(true);
useEffect(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
return isMountedRef;
}Usage After Refactor
import { useMounted } from '@/hooks/useMounted';
function MySheet() {
const isMounted = useMounted();
const handleSave = async () => {
await saveData();
if (isMounted.current) {
dismiss();
}
};
}Benefits
- DRY principle - single source of truth
- Consistent behavior across components
- Easier to test in isolation
- Self-documenting through JSDoc
Acceptance Criteria
- Create
hooks/useMounted.tswith JSDoc - Create
__tests__/hooks/useMounted.test.ts - Update all 4 sheet components to use hook
- No functionality regression
Related to #279 (Daily Codebase Review)
Metadata
Metadata
Assignees
Labels
refactorCode refactoringCode refactoring