Skip to content

Commit

Permalink
Merge ba12d64 into ef2ff79
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesplease committed Jun 15, 2021
2 parents ef2ff79 + ba12d64 commit 9b16b67
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "@please/lrud",
"version": "0.0.13-beta.4",
"version": "0.0.13-beta.5",
"description": "A React library for managing focus in TV apps.",
"main": "es/index.js",
"module": "es/index.js",
Expand Down
103 changes: 92 additions & 11 deletions src/focus-node.tsx
Expand Up @@ -98,6 +98,73 @@ export function FocusNode(
) {
const elRef = useRef(null);

// We store the callbacks in a ref so that we can pass a wrapper function into the underlying
// focus node within the focus state. This wrapper function stays constant throughout the lifetime
// of the node, and that wrapper calls this ref.
// The reason for this roundabout solution is to avoid a situation of an infinite rerenders: if the node
// itself were updated when the callbacks changed, then this would cause all consumers of the store state
// to render. Unless consumers are using `useCallback`, this would recreate the handlers, creating an infinite
// loop.
const callbacksRef = useRef({
onKey,
onArrow,
onLeft,
onRight,
onUp,
onDown,
onSelected,
onBack,

onMove,
onGridMove,

onFocused,
onBlurred,

onClick,
onMouseOver,
});

useEffect(() => {
callbacksRef.current = {
onKey,
onArrow,
onLeft,
onRight,
onUp,
onDown,
onSelected,
onBack,

onMove,
onGridMove,

onFocused,
onBlurred,

onClick,
onMouseOver,
};
}, [
onKey,
onArrow,
onLeft,
onRight,
onUp,
onDown,
onSelected,
onBack,

onMove,
onGridMove,

onFocused,
onBlurred,

onClick,
onMouseOver,
]);

useImperativeHandle(
ref,
// I may need to update this based on this comment to make TS happy:
Expand Down Expand Up @@ -146,6 +213,20 @@ export function FocusNode(
const wrapGridColumnsValue =
typeof wrapGridColumns === 'boolean' ? wrapGridColumns : wrapping;

function createCallbackWrapper(fnName: string) {
return function callbackWrapper(...args: any[]) {
// @ts-ignore
if (
callbacksRef.current &&
// @ts-ignore
typeof callbacksRef.current[fnName] === 'function'
) {
// @ts-ignore
callbacksRef.current[fnName](...args);
}
};
}

const nodeDefinition: NodeDefinition = {
elRef,
focusId: nodeId,
Expand All @@ -163,17 +244,17 @@ export function FocusNode(
defaultFocusColumn: defaultFocusColumn ?? 0,
defaultFocusRow: defaultFocusRow ?? 0,

onKey,
onArrow,
onLeft,
onRight,
onUp,
onDown,
onSelected,
onBack,

onMove,
onGridMove,
onKey: createCallbackWrapper('onKey'),
onArrow: createCallbackWrapper('onArrow'),
onLeft: createCallbackWrapper('onLeft'),
onRight: createCallbackWrapper('onRight'),
onUp: createCallbackWrapper('onUp'),
onDown: createCallbackWrapper('onDown'),
onSelected: createCallbackWrapper('onSelected'),
onBack: createCallbackWrapper('onBack'),

onMove: createCallbackWrapper('onMove'),
onGridMove: createCallbackWrapper('onGridMove'),

initiallyDisabled: Boolean(disabled),
onMountAssignFocusTo,
Expand Down

0 comments on commit 9b16b67

Please sign in to comment.