---
title: Tecles de drecera
image: /images/user-guide/table-views/table.png
---

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

## Introducció

Quan necessites escoltar una tecla de drecera, normalment utilitzaries l'escoltador d'events `onKeyDown`.

A `twenty-front`, però, pots tenir conflictes entre les mateixes tecles de drecera que s'utilitzen en components diferents, muntats alhora.

Per exemple, si tens una pàgina que escolta per la tecla Enter, i un modal que escolta per la tecla Enter, amb un component Select dins d'aquest modal que escolta per la tecla Enter, pots tenir un conflicte quan tots estan muntats alhora.

## El hook `useScopedHotkeys`

Per solucionar aquest problema, tenim un hook personalitzat que permet escoltar les tecles de drecera sense cap conflicte.

Col·loques aquest hook en un component, i escoltarà les tecles de drecera només quan el component estigui muntat I quan l'**àmbit de tecles de drecera** especificat estigui actiu.

## Com escoltar les tecles de drecera a la pràctica?

Hi ha dos passos implicats en configurar l'escolta de tecles de drecera:

1. Estableix l'[àmbit de tecles de drecera](#what-is-a-hotkey-scope-) que escoltarà les tecles de drecera
2. Utilitza el hook `useScopedHotkeys` per escoltar les tecles de drecera

Configurar àmbits de tecles de drecera és necessari fins i tot en pàgines senzilles, perquè altres elements de la interfície d'usuari, com el menú esquerre o el menú de comandes, també poden escoltar les tecles de drecera.

## Casos d'ús per a tecles de drecera

En general, tindràs dos casos d'ús que requereixen tecles de drecera:

1. En una pàgina o un component muntat en una pàgina
2. En un component de tipus modal que pren el focus a causa d'una acció de l'usuari

El segon cas d'ús pot ocórrer de forma recursiva: un desplegable en un modal, per exemple.

### Escoltar tecles de drecera en una pàgina

Exemple:

```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>;
};
```

### Escoltar tecles de drecera en un component de tipus modal

Per a aquest exemple, utilitzarem un component modal que escolta per la tecla Escape per indicar al seu pare que el tanqui.

Aquí la interacció de l'usuari està canviant l'àmbit.

```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>;
};
```

Llavors, en el component modal:

```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>;
};
```

És important utilitzar aquest patró quan no estàs segur que només utilitzar un useEffect amb muntatge/desmuntatge serà suficient per evitar conflictes.

Aquests conflictes poden ser difícils de resoldre, i pot passar més sovint del que sembla amb useEffects.

## Què és un àmbit de tecles de drecera?

Un àmbit de tecles de drecera és una cadena que representa un context en el qual les tecles de drecera estan actives. Generalment està codificat com un enum.

Quan canvies l'àmbit de tecles de drecera, les tecles que escolten aquest àmbit estaran activades i les tecles que escolten altres àmbits estaran desactivades.

Pots establir només un àmbit a la vegada.

Com a exemple, els àmbits de tecles de drecera per a cada pàgina estan definits en l'enum `PageHotkeyScope`:

```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',
}
```

Internament, l'àmbit seleccionat actualment es guarda en un estat Recoil que es comparteix a través de l'aplicació:

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

Però aquest estat Recoil no s'hauria de manejar mai manualment! Veurem com utilitzar-lo a la següent secció.

## Com funciona internament?

Hem fet un embolcall fi a sobre de [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) que el fa més eficient i evita renderitzacions innecessàries.

També creem un estat Recoil per gestionar l'estat de l'àmbit de tecles de drecera i fer-ho disponible arreu de l'aplicació.