Skip to content

Commit

Permalink
Pressability: Support Lazy Hook Initialization
Browse files Browse the repository at this point in the history
Summary:
Changes `usePressability` so that it accepts a nullable `config` argument.

This makes it possible for a component to use `usePressability` and lazily allocate the `config` and subsequent instance of `Pressability`. This can be useful for components that are commonly allocated but seldom pressed because it lets many usages of `usePressability` avoid allocating many extraneous objects.

Changelog:
[Internal]

Reviewed By: kacieb

Differential Revision: D23708206

fbshipit-source-id: 4a5063067131ce8c957fb16c49a2045e8c0b19fa
  • Loading branch information
yungsters authored and facebook-github-bot committed Sep 29, 2020
1 parent 0a0d2c9 commit 9da4d87
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
14 changes: 9 additions & 5 deletions Libraries/Components/Pressable/Pressable.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ function Pressable(props: Props, forwardedRef): React.Node {

const hitSlop = normalizeRect(props.hitSlop);

const restPropsWithDefaults: React.ElementConfig<typeof View> = {
...restProps,
...android_rippleConfig?.viewProps,
accessible: accessible !== false,
focusable: focusable !== false,
hitSlop,
};

const config = useMemo(
() => ({
disabled,
Expand Down Expand Up @@ -219,12 +227,8 @@ function Pressable(props: Props, forwardedRef): React.Node {

return (
<View
{...restProps}
{...restPropsWithDefaults}
{...eventHandlers}
{...android_rippleConfig?.viewProps}
accessible={accessible !== false}
focusable={focusable !== false}
hitSlop={hitSlop}
ref={viewRef}
style={typeof style === 'function' ? style({pressed}) : style}
collapsable={false}>
Expand Down
25 changes: 17 additions & 8 deletions Libraries/Pressability/usePressability.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,37 @@ import Pressability, {
} from './Pressability';
import {useEffect, useRef} from 'react';

/**
* Creates a persistent instance of `Pressability` that automatically configures
* itself and resets. Accepts null `config` to support lazy initialization. Once
* initialized, will not un-initialize until the component has been unmounted.
*/
export default function usePressability(
config: PressabilityConfig,
): EventHandlers {
config: ?PressabilityConfig,
): ?EventHandlers {
const pressabilityRef = useRef<?Pressability>(null);
if (pressabilityRef.current == null) {
if (config != null && pressabilityRef.current == null) {
pressabilityRef.current = new Pressability(config);
}
const pressability = pressabilityRef.current;

// On the initial mount, this is a no-op. On updates, `pressability` will be
// re-configured to use the new configuration.
useEffect(() => {
pressability.configure(config);
if (config != null && pressability != null) {
pressability.configure(config);
}
}, [config, pressability]);

// On unmount, reset pending state and timers inside `pressability`. This is
// a separate effect because we do not want to reset when `config` changes.
useEffect(() => {
return () => {
pressability.reset();
};
if (pressability != null) {
return () => {
pressability.reset();
};
}
}, [pressability]);

return pressability.getEventHandlers();
return pressability == null ? null : pressability.getEventHandlers();
}

0 comments on commit 9da4d87

Please sign in to comment.