diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2023-02-23 10:15:28 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2023-02-27 10:57:36 +0100 |
| commit | 955f1cd2c5ba4594c736cbc0ed49d770400e0062 (patch) | |
| tree | e6c5ebcf7d62ec6b0dda4abc40d58f90f2cc1fd7 | |
| parent | f49760525dbd4bfb5e19a0231d1d8b7a41f76ce1 (diff) | |
| download | mullvadvpn-955f1cd2c5ba4594c736cbc0ed49d770400e0062.tar.xz mullvadvpn-955f1cd2c5ba4594c736cbc0ed49d770400e0062.zip | |
Fix back action collision
| -rw-r--r-- | gui/src/renderer/components/KeyboardNavigation.tsx | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/gui/src/renderer/components/KeyboardNavigation.tsx b/gui/src/renderer/components/KeyboardNavigation.tsx index f88b4f31e9..fc11e54699 100644 --- a/gui/src/renderer/components/KeyboardNavigation.tsx +++ b/gui/src/renderer/components/KeyboardNavigation.tsx @@ -12,9 +12,15 @@ interface IKeyboardNavigationProps { // Listens for and handles keyboard shortcuts export default function KeyboardNavigation(props: IKeyboardNavigationProps) { const history = useHistory(); - const [backAction, setBackAction] = useState<BackActionFn>(); + const [backAction, setBackActionImpl] = useState<BackActionFn>(); const location = useLocation(); + // Since the backaction is now a function we need to make sure it's not called when setting the + // state. + const setBackAction = useCallback((backAction: BackActionFn | undefined) => { + setBackActionImpl(() => backAction); + }, []); + const handleKeyDown = useCallback( (event: KeyboardEvent) => { if (event.key === 'Escape') { @@ -66,17 +72,28 @@ interface IBackActionProps { // either by pressing the back button in the navigation bar or by pressing escape. export function BackAction(props: IBackActionProps) { const backActionContext = useContext(BackActionContext); - const [childrenBackAction, setChildrenBackAction] = useState<BackActionFn>(); + const [childrenBackAction, setChildrenBackActionImpl] = useState<BackActionFn>(); + + // Since the backaction is now a function we need to make sure it's not called when setting the + // state. + const setChildrenBackAction = useCallback((backAction: BackActionFn | undefined) => { + setChildrenBackActionImpl(() => backAction); + }, []); - const backActionConfiguration = childrenBackAction ?? props.action; + // Each back action needs to be unique to make `removeBackAction` work. This is accomplished by + // wrapping it in a callback. This was an issue since `history.pop`, which is commonly used as a + // back action, is the same function for every component. + const backAction = useCallback(() => { + (childrenBackAction ?? props.action)(); + }, [props.action, childrenBackAction]); // Every time the action or the disabled property changes the action needs to be reregistered. useEffect((): (() => void) | void => { - if (!props.disabled && backActionConfiguration) { - backActionContext.registerBackAction(backActionConfiguration); - return () => backActionContext.removeBackAction(backActionConfiguration); + if (!props.disabled && backAction) { + backActionContext.registerBackAction(backAction); + return () => backActionContext.removeBackAction(backAction); } - }, [props.disabled, backActionConfiguration]); + }, [props.disabled, backAction]); // Every back action keeps track of the back actions in its subtree. This makes it possible to // always use the action furthest down in the tree. @@ -109,7 +126,7 @@ function BackActionTracker(props: IBackActionTracker) { [backActions], ); - useEffect(() => props.registerBackAction(() => backActions.at(0)), [backActions]); + useEffect(() => props.registerBackAction(backActions.at(0)), [backActions]); return ( <BackActionContext.Provider value={backActionContext}> |
