fix(record-table): guard against undefined recordField during column resize
https://sonarly.com/issue/5904?type=bug When resizing a table column header on the messageThreads page, `recordField` can be undefined because `visibleRecordFields` changes mid-resize, causing an unhandled throw that crashes the page. Fix: Replaced `throwIfNotDefined(recordField, 'recordField')` with graceful `isDefined` early returns in both `handleResizeHandlerMove` and `handleResizeHandlerEnd` callbacks in `useResizeTableHeader.ts`. **Changes:** 1. **Import swap**: Replaced `throwIfNotDefined` with `isDefined` from `twenty-shared/utils` — the same utility already used extensively in sibling files in this directory. 2. **`handleResizeHandlerMove` (line 96)**: Changed from `throwIfNotDefined(recordField, 'recordField')` to `if (!isDefined(recordField)) return;`. When `visibleRecordFields` changes mid-resize and the resized field is no longer in the array, the move handler now silently skips the frame instead of throwing on every mousemove event. 3. **`handleResizeHandlerEnd` (line 164-172)**: Changed from `throwIfNotDefined` to an `isDefined` check that also **resets all resize state** (offset, pointer position, field metadata ID, drag selection) before returning. This prevents the user from getting stuck in a broken resize state when the field disappears mid-resize — the next interaction will start clean. The `isDefined` utility is a proper TypeScript type guard (`value is NonNullable<T>`), so type narrowing after the check is preserved — the code below the guard can still access `recordField.size`, `recordField.id`, etc. without type errors.
This commit is contained in:
+9
-4
@@ -28,7 +28,7 @@ import { useCallback, useState } from 'react';
|
||||
import {
|
||||
findById,
|
||||
findByProperty,
|
||||
throwIfNotDefined,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
export const useResizeTableHeader = () => {
|
||||
@@ -93,7 +93,7 @@ export const useResizeTableHeader = () => {
|
||||
({ x }) => {
|
||||
if (!initialPointerPositionX) return;
|
||||
|
||||
throwIfNotDefined(recordField, 'recordField');
|
||||
if (!isDefined(recordField)) return;
|
||||
|
||||
const newResizeOffset = x - initialPointerPositionX;
|
||||
|
||||
@@ -162,9 +162,14 @@ export const useResizeTableHeader = () => {
|
||||
const store = useStore();
|
||||
|
||||
const handleResizeHandlerEnd = useCallback(async () => {
|
||||
throwIfNotDefined(recordField, 'recordField');
|
||||
if (!isDefined(recordField) || !resizedFieldMetadataId) {
|
||||
store.set(resizeFieldOffset, 0);
|
||||
setInitialPointerPositionX(null);
|
||||
setResizedFieldMetadataId(null);
|
||||
setDragSelectionStartEnabled(true);
|
||||
|
||||
if (!resizedFieldMetadataId) return;
|
||||
return;
|
||||
}
|
||||
|
||||
const currentResizeFieldOffset = store.get(resizeFieldOffset);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user