Repository: twentyhq/twenty
File: packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleColumnSort.ts (TypeScript)

Code before:
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { type RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { ViewSortDirection } from '~/generated/graphql';

type UseHandleToggleColumnSortProps = {
  objectMetadataItemId: string;
};

export const useHandleToggleColumnSort = ({
  objectMetadataItemId,
}: UseHandleToggleColumnSortProps) => {
  const { objectMetadataItem } = useObjectMetadataItemById({
    objectId: objectMetadataItemId,
  });

  const { columnDefinitions } =
    useColumnDefinitionsFromObjectMetadata(objectMetadataItem);

  const { upsertRecordSort } = useUpsertRecordSort();

  const currentRecordSorts = useRecoilComponentValue(
    currentRecordSortsComponentState,
  );

  const handleToggleColumnSort = useCallback(
    async (fieldMetadataId: string) => {
      const correspondingColumnDefinition = columnDefinitions.find(
        (columnDefinition) =>
          columnDefinition.fieldMetadataId === fieldMetadataId,
      );

      if (!isDefined(correspondingColumnDefinition)) return;

      const existingSort = currentRecordSorts.find(
        (sort) => sort.fieldMetadataId === fieldMetadataId,
      );

      const newSort: RecordSort = {
        id: existingSort?.id ?? v4(),
        fieldMetadataId,
        direction: existingSort
          ? existingSort.direction === ViewSortDirection.ASC
            ? ViewSortDirection.DESC
            : ViewSortDirection.ASC
          : ViewSortDirection.ASC,
      };

Review comment (suggestion):
we should not subscribe to the state using useRecoilComponentValue

this makes the hook reactive to this state which the caller will not expect as we are implementing a sync action.

Instead, make handleToggleColumnSort a recoilCallback and read existing sorts from the snapshot, they are many examples in the code

Code after:
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { type RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { ViewSortDirection } from '~/generated/graphql';

type UseHandleToggleColumnSortProps = {
  objectMetadataItemId: string;
};

export const useHandleToggleColumnSort = ({
  objectMetadataItemId,
}: UseHandleToggleColumnSortProps) => {
  const { objectMetadataItem } = useObjectMetadataItemById({
    objectId: objectMetadataItemId,
  });

  const { columnDefinitions } =
    useColumnDefinitionsFromObjectMetadata(objectMetadataItem);

  const { upsertRecordSort } = useUpsertRecordSort();

  const currentRecordSortsCallbackState = useRecoilComponentCallbackState(
    currentRecordSortsComponentState,
  );

  const handleToggleColumnSort = useRecoilCallback(
    ({ snapshot }) =>
      (fieldMetadataId: string) => {
        const correspondingColumnDefinition = columnDefinitions.find(
          (columnDefinition) =>
            columnDefinition.fieldMetadataId === fieldMetadataId,
        );

        if (!isDefined(correspondingColumnDefinition)) return;

        const currentRecordSorts = getSnapshotValue(
          snapshot,
          currentRecordSortsCallbackState,
        );

        const existingSort = currentRecordSorts.find(
          (sort) => sort.fieldMetadataId === fieldMetadataId,
        );

        const newSort: RecordSort = {
          id: existingSort?.id ?? v4(),
          fieldMetadataId,