Skip to content

Commit

Permalink
Removed custom "useEffectOnce" hook, added more logs (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
asgvard authored May 11, 2023
1 parent 4e9e4ec commit a6feb4d
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 63 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# [1.3.1]
## Added
- Extra debug logs, printing focusable components data in addition to DOM nodes.
- Extra call to set `focused` state to `false` on unmount. This is to support "double-mount" in Strict mode in React 18.

## Changed
- [Potentially Breaking] Auto restore focus when the item is removed is now happening with a slight debounced delay.

## Removed
- Custom `useEffectOnce` hook that introduced issues with unmounted components being remained as focusable.

# [1.3.0]
## Added
- new `init` config option `shouldFocusDOMNode` that focuses the underlying _accessible_ DOM node too.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@noriginmedia/norigin-spatial-navigation",
"version": "1.3.0",
"version": "1.3.1",
"description": "React hooks based Spatial Navigation solution",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
59 changes: 46 additions & 13 deletions src/SpatialNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import findKey from 'lodash/findKey';
import forEach from 'lodash/forEach';
import forOwn from 'lodash/forOwn';
import throttle from 'lodash/throttle';
import debounce from 'lodash/debounce';
import difference from 'lodash/difference';
import measureLayout, { getBoundingClientRect } from './measureLayout';
import VisualDebugger from './VisualDebugger';
Expand Down Expand Up @@ -39,6 +40,8 @@ const DIAGONAL_SLICE_WEIGHT = 1;
*/
const MAIN_COORDINATE_WEIGHT = 5;

const AUTO_RESTORE_FOCUS_DELAY = 300;

const DEBUG_FN_COLORS = ['#0FF', '#FF0', '#F0F'];

const THROTTLE_OPTIONS = {
Expand Down Expand Up @@ -219,6 +222,8 @@ class SpatialNavigationService {

private logIndex: number;

private setFocusDebounced: DebouncedFunc<any>;

/**
* Used to determine the coordinate that will be used to filter items that are over the "edge"
*/
Expand Down Expand Up @@ -554,6 +559,11 @@ class SpatialNavigationService {
this.setKeyMap = this.setKeyMap.bind(this);
this.getCurrentFocusKey = this.getCurrentFocusKey.bind(this);

this.setFocusDebounced = debounce(this.setFocus, AUTO_RESTORE_FOCUS_DELAY, {
leading: false,
trailing: true
});

this.debug = false;
this.visualDebugger = null;

Expand Down Expand Up @@ -879,7 +889,8 @@ class SpatialNavigationService {
'smartNavigate',
'currentComponent',
currentComponent ? currentComponent.focusKey : undefined,
currentComponent ? currentComponent.node : undefined
currentComponent ? currentComponent.node : undefined,
currentComponent
);

if (currentComponent) {
Expand Down Expand Up @@ -935,7 +946,8 @@ class SpatialNavigationService {
'siblings',
`${siblings.length} elements:`,
siblings.map((sibling) => sibling.focusKey).join(', '),
siblings.map((sibling) => sibling.node)
siblings.map((sibling) => sibling.node),
siblings.map((sibling) => sibling)
);
}

Expand Down Expand Up @@ -963,7 +975,8 @@ class SpatialNavigationService {
'smartNavigate',
'nextComponent',
nextComponent ? nextComponent.focusKey : undefined,
nextComponent ? nextComponent.node : undefined
nextComponent ? nextComponent.node : undefined,
nextComponent
);

if (nextComponent) {
Expand Down Expand Up @@ -1159,6 +1172,12 @@ class SpatialNavigationService {

this.updateLayout(focusKey);

this.log(
'addFocusable',
'Component added: ',
this.focusableComponents[focusKey]
);

/**
* If for some reason this component was already focused before it was added, call the update
*/
Expand All @@ -1171,7 +1190,11 @@ class SpatialNavigationService {
const componentToRemove = this.focusableComponents[focusKey];

if (componentToRemove) {
const { parentFocusKey } = componentToRemove;
const { parentFocusKey, onUpdateFocus } = componentToRemove;

onUpdateFocus(false);

this.log('removeFocusable', 'Component removed: ', componentToRemove);

delete this.focusableComponents[focusKey];

Expand All @@ -1189,18 +1212,21 @@ class SpatialNavigationService {
return;
}

forEach(this.focusableComponents, (component) => {
if (component.parentFocusKey === focusKey && component.focusable) {
// eslint-disable-next-line no-param-reassign
component.parentFocusKey = parentFocusKey;
}
});

/**
* If the component was also focused at this time, focus another one
* If the component was also focused at this time, focus its parent -> it will focus another child
*/
if (isFocused && parentComponent && parentComponent.autoRestoreFocus) {
this.setFocus(parentFocusKey);
this.log(
'removeFocusable',
'Auto restoring focus to: ',
parentFocusKey
);

/**
* Focusing parent with a slight delay
* This is to avoid multiple focus restorations if multiple children getting unmounted in one render cycle
*/
this.setFocusDebounced(parentFocusKey);
}
}
}
Expand Down Expand Up @@ -1233,6 +1259,8 @@ class SpatialNavigationService {
this.getNodeLayoutByFocusKey(this.focusKey),
focusDetails
);

this.log('setCurrentFocusedKey', 'onBlur', oldComponent);
}

this.focusKey = newFocusKey;
Expand All @@ -1249,6 +1277,8 @@ class SpatialNavigationService {
this.getNodeLayoutByFocusKey(this.focusKey),
focusDetails
);

this.log('setCurrentFocusedKey', 'onFocus', newComponent);
}
}

Expand Down Expand Up @@ -1385,6 +1415,9 @@ class SpatialNavigationService {
}

setFocus(focusKey: string, focusDetails: FocusDetails = {}) {
// Cancel any pending auto-restore focus calls if we are setting focus manually
this.setFocusDebounced.cancel();

if (!this.enabled) {
return;
}
Expand Down
44 changes: 0 additions & 44 deletions src/useEffectOnce.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/useFocusable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
KeyPressDetails
} from './SpatialNavigation';
import { useFocusContext } from './useFocusedContext';
import useEffectOnce from './useEffectOnce';

export type EnterPressHandler<P = object> = (
props: P,
Expand Down Expand Up @@ -140,7 +139,7 @@ const useFocusableHook = <P>({
[focusKey]
);

useEffectOnce(() => {
useEffect(() => {
const node = ref.current;

SpatialNavigation.addFocusable({
Expand Down Expand Up @@ -168,7 +167,7 @@ const useFocusableHook = <P>({
focusKey
});
};
});
}, []); // eslint-disable-line react-hooks/exhaustive-deps

useEffect(() => {
const node = ref.current;
Expand Down

0 comments on commit a6feb4d

Please sign in to comment.