---
title: Kortkommandon
image: /images/user-guide/table-views/table.png
---

<Frame>
  <img src="/images/user-guide/table-views/table.png" alt="Header" />
</Frame>

## Introduktion

När du behöver lyssna på ett kortkommando använder du normalt `onKeyDown`-händelsehanteraren.

I `twenty-front` kan du dock ha konflikter mellan samma kortkommandon som används i olika komponenter som är monterade samtidigt.

Till exempel, om du har en sida som lyssnar efter Enter-tangenten, och en modal som lyssnar efter Enter-tangenten, med en Välj-komponent inuti den modalen som lyssnar efter Enter-tangenten, kan du ha en konflikt när alla är monterade samtidigt.

## `useScopedHotkeys`-haken

För att hantera detta problem har vi en anpassad hook som gör det möjligt att lyssna på kortkommandon utan några konflikter.

Du placerar den i en komponent, och den kommer bara lyssna på kortkommandona när komponenten är monterad OCH när det specifika **kortkommandoområdet** är aktivt.

## Hur lyssnar man på kortkommandon i praktiken?

Det finns två steg inblandade i att sätta upp lyssnande på kortkommandon:

1. Sätt [kortkommandoområdet](#vad-är-ett-kortkommandoområde-) som kommer lyssna på kortkommandon
2. Använd `useScopedHotkeys`-hooken för att lyssna på kortkommandon

Att sätta upp kortkommandoområden är nödvändigt även på enkla sidor, eftersom andra UI-element som vänstermeny eller kommandomeny också kan lyssna på kortkommandon.

## Användningsfall för kortkommandon

Generellt kommer du ha två användningsfall som kräver kortkommandon:

1. På en sida eller en komponent monterad på en sida
2. I en modal-typ av komponent som tar fokus på grund av en användaråtgärd

Det andra användningsfallet kan inträffa rekursivt: en dropdown i en modal till exempel.

### Lyssna på kortkommandon på en sida

Exempel :

```tsx
const PageListeningEnter = () => {
  const {
    setHotkeyScopeAndMemorizePreviousScope,
    goBackToPreviousHotkeyScope,
  } = usePreviousHotkeyScope();

  // 1. Set the hotkey scope in a useEffect
  useEffect(() => {
    setHotkeyScopeAndMemorizePreviousScope(
      ExampleHotkeyScopes.ExampleEnterPage,
    );

    // Revert to the previous hotkey scope when the component is unmounted
    return () => {
      goBackToPreviousHotkeyScope();
    };
  }, [goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope]);

  // 2. Use the useScopedHotkeys hook
  useScopedHotkeys(
    Key.Enter,
    () => {
      // Some logic executed on this page when the user presses Enter
      // ...
    },
    ExampleHotkeyScopes.ExampleEnterPage,
  );

  return <div>My page that listens for Enter</div>;
};
```

### Lyssna på kortkommandon i en modal-typ av komponent

För detta exempel använder vi en modalkomponent som lyssnar efter Escape-tangenten för att tala om för dess förälder att stänga den.

Här förändrar användarinteraktionen området.

```tsx
const ExamplePageWithModal = () => {
  const [showModal, setShowModal] = useState(false);

  const {
    setHotkeyScopeAndMemorizePreviousScope,
    goBackToPreviousHotkeyScope,
  } = usePreviousHotkeyScope();

  const handleOpenModalClick = () => {
    // 1. Set the hotkey scope when user opens the modal
    setShowModal(true);
    setHotkeyScopeAndMemorizePreviousScope(
      ExampleHotkeyScopes.ExampleModal,
    );
  };

  const handleModalClose = () => {
    // 1. Revert to the previous hotkey scope when the modal is closed
    setShowModal(false);
    goBackToPreviousHotkeyScope();
  };

  return <div>
    <h1>My page with a modal</h1>
    <button onClick={handleOpenModalClick}>Open modal</button>
    {showModal && <MyModalComponent onClose={handleModalClose} />}
  </div>;
};
```

Sedan i modalkomponenten:

```tsx
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
  // 2. Use the useScopedHotkeys hook to listen for Escape.
  // Note that escape is a common hotkey that could be used by many other components
  // So it's important to use a hotkey scope to avoid conflicts
  useScopedHotkeys(
    Key.Escape,
    () => {
      onClose()
    },
    ExampleHotkeyScopes.ExampleModal,
  );

  return <div>My modal component</div>;
};
```

Det är viktigt att använda detta mönster när du inte är säker på att bara använda useEffect med montering/avmontering kommer att vara tillräckligt för att undvika konflikter.

Dessa konflikter kan vara svåra att felsöka, och det kan inträffa oftare än man tror med useEffects.

## Vad är ett kortkommandoområde?

Ett kortkommandoområde är en sträng som representerar ett sammanhang där kortkommandona är aktiva. Det är vanligtvis kodad som ett enum.

När du ändrar kortkommandoområdet kommer kortkommandona som lyssnar på detta område att aktiveras och de som lyssnar på andra områden avaktiveras.

Du kan bara ställa in ett område åt gången.

Som ett exempel definieras kortkommandoområden för varje sida i `PageHotkeyScope`-enumet:

```tsx
export enum PageHotkeyScope {
  Settings = 'settings',
  CreateWorkspace = 'create-workspace',
  SignInUp = 'sign-in-up',
  CreateProfile = 'create-profile',
  PlanRequired = 'plan-required',
  ShowPage = 'show-page',
  PersonShowPage = 'person-show-page',
  CompanyShowPage = 'company-show-page',
  CompaniesPage = 'companies-page',
  PeoplePage = 'people-page',
  OpportunitiesPage = 'opportunities-page',
  ProfilePage = 'profile-page',
  WorkspaceMemberPage = 'workspace-member-page',
  TaskPage = 'task-page',
}
```

Internt lagras det för närvarande valda området i ett Recoil-state som delas över hela applikationen:

```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
  key: 'currentHotkeyScopeState',
  defaultValue: INITIAL_HOTKEYS_SCOPE,
});
```

Men detta Recoil-state ska aldrig hanteras manuellt! Vi kommer gå igenom hur man använder det i nästa avsnitt.

## Hur fungerar det internt?

Vi skapade en tunn wrapper ovanpå [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) som gör den mer prestandaoptimerad och undviker onödiga omrenderingar.

Vi skapar också ett Recoil-state för att hantera kortkommandoområdesstatusen och göra det tillgängligt överallt i applikationen.