--- title: Skróty klawiszowe image: /images/user-guide/table-views/table.png --- Header ## Wprowadzenie Gdy potrzebujesz nasłuchiwać skrótu klawiszowego, zazwyczaj używasz nasłuchiwania zdarzenia `onKeyDown`. Jednak w `twenty-front` mogą wystąpić konflikty między tymi samymi skrótami używanymi w różnych komponentach, zamontowanymi w tym samym czasie. Na przykład, jeśli masz stronę nasłuchującą klawisza Enter i modal nasłuchujący klawisza Enter z komponentem Select w środku, który również nasłuchuje klawisza Enter, możesz mieć konflikt, gdy wszystkie są zamontowane jednocześnie. ## The `useScopedHotkeys` hook Aby rozwiązać ten problem, mamy własny hak, który umożliwia nasłuchiwanie skrótów klawiszowych bez konfliktu. Umieszczasz go w komponencie, a będzie nasłuchiwać skrótów klawiszowych tylko wtedy, gdy komponent jest zamontowany I gdy określony **zakres skrótu klawiszowego** jest aktywny. ## Jak praktycznie nasłuchiwać skrótów klawiszowych? Ustawianie nasłuchiwania skrótów klawiszowych wymaga dwóch kroków: 1. Określ [zakres skrótu klawiszowego](#what-is-a-hotkey-scope-), który będzie nasłuchiwać skrótów klawiszowych 2. Use the `useScopedHotkeys` hook to listen to hotkeys Konfiguracja zakresów skrótów klawiszowych jest wymagana nawet na prostych stronach, ponieważ inne elementy interfejsu, jak menu po lewej czy menu komend, mogą także nasłuchiwać skrótów klawiszowych. ## Przykłady użycia skrótów klawiszowych Ogólnie rzecz biorąc, występują dwa przypadki użycia wymagające skrótów klawiszowych: 1. Na stronie lub w komponencie zamontowanym na stronie 2. W komponencie typu modalnego, który przejmuje fokus ze względu na działanie użytkownika Drugi przypadek użycia może wystąpić rekurencyjnie: na przykład w rozwijanym menu w modalu. ### Nasłuchiwanie skrótów klawiszowych na stronie Przykład: ```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
My page that listens for Enter
; }; ``` ### Nasłuchiwanie skrótów klawiszowych w komponencie typu modalnego W tym przykładzie użyjemy komponentu modalnego, który nasłuchuje klawisza Escape, aby poinformować nadrzędny komponent o konieczności jego zamknięcia. Tutaj działanie użytkownika zmienia zakres. ```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

My page with a modal

{showModal && }
; }; ``` Następnie w komponencie modalnym: ```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
My modal component
; }; ``` Ważne jest, aby używać tego wzorca, gdy nie jesteś pewny, że samo użycie useEffect z mount/unmount wystarczy, aby uniknąć konfliktów. Te konflikty mogą być trudne do debugowania i mogą występować częściej niż się wydaje przy użyciu useEffects. ## Co to jest zakres skrótu klawiszowego? Zakres skrótu klawiszowego to ciąg znaków, który reprezentuje kontekst, w którym skróty klawiszowe są aktywne. Zazwyczaj jest kodowany jako enum. Gdy zmienisz zakres skrótu klawiszowego, skróty nasłuchujące tego zakresu zostaną włączone, a te, które nasłuchują innych zakresów, zostaną wyłączone. Możesz ustawić tylko jeden zakres naraz. As an example, the hotkey scopes for each page are defined in the `PageHotkeyScope` enum: ```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', } ``` Internally, the currently selected scope is stored in a Recoil state that is shared across the application : ```tsx export const currentHotkeyScopeState = createState({ key: 'currentHotkeyScopeState', defaultValue: INITIAL_HOTKEYS_SCOPE, }); ``` Ale ten stan Recoil nigdy nie powinien być obsługiwany ręcznie! Pokażemy, jak go używać w następnej sekcji. ## Jak to działa wewnętrznie? Stworzyliśmy cienką warstwę na [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), która sprawia, że jest bardziej wydajna i unika niepotrzebnych ponownych renderowań. Tworzymy również stan Recoil, aby obsługiwać stan zakresu skrótu klawiszowego i udostępniać go wszędzie w aplikacji.