Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

likhith/migrated hooks folder to ts #58

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import React, { RefObject } from 'react';

export const useBlockScroll = target_ref => {
export const useBlockScroll = (target_ref: RefObject<HTMLElement>) => {
React.useEffect(() => {
if (!target_ref) return undefined;

const getScrollableParentElement = elem => {
const getScrollableParentElement: (prop: HTMLElement | null) => HTMLElement | null = (
elem: HTMLElement | null
) => {
if (!elem) return null;
if (elem.classList.contains('dc-themed-scrollbars') && elem.scrollHeight > elem.clientHeight) return elem;
return getScrollableParentElement(elem.parentElement);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

export const useConstructor = (callBack = () => {}) => {
export const useConstructor = (callBack = () => undefined) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useConstructor = (callBack = () => undefined) => {
export const useConstructor = (callBack = () => {}) => {

@likhith-deriv no need to add a type for callBack here as it's inferred from the default value🙂:
Screenshot 2022-10-07 at 12 44 47

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

callBack = () => {} this threw an error that empty arrow functions cannot be used. Hence changed the {} to undefined

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, we have to declare the callback type, otherwise TS will think that we can accept here only the callbacks which return undefined:
Screenshot 2022-10-07 at 17 41 30

Suggested change
export const useConstructor = (callBack = () => undefined) => {
export const useConstructor = (callBack: () => void = () => undefined) => {

🙂

const is_called_ref = React.useRef(false);
if (!is_called_ref.current) {
callBack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isDeepEqual } from '@deriv/shared';

// Note: Do not use this effect on huge objects or objects with
// circular references as performance may suffer.
export const useDeepEffect = (callback, dependencies) => {
export const useDeepEffect = (callback: () => void, dependencies: any) => {
const prev_dependencies = React.useRef(null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useDeepEffect = (callback: () => void, dependencies: any) => {
const prev_dependencies = React.useRef(null);
export const useDeepEffect = (callback: () => void, dependencies: unknown[]) => {
const prev_dependencies = React.useRef<unknown[] | null>(null);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dependencies can be an array or an object since isDeepEqual supports both. And useDeepEffect is not used anywhere yet. So should it be unknown[]?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@likhith-deriv to me, the way dependencies parameter is named suggests that it's a list of dependencies (= array), so it seems logical to pass an array of dependencies to it, and use useDeepEffect as a custom analogue of a real useEffect which accepts an array of dependencies. Yes, sure, isDeepEqual supports any values and it's important to us that it accepts arrays because we want to compare 2 lists (=arrays) of dependencies with its help, so we just say that here we'll pass an array to it. Btw, since useEffect can be called without an array of dependencies at all, it would be even better to make this parameter optional to make it look even nore like a real useEffect 😊:

Suggested change
export const useDeepEffect = (callback: () => void, dependencies: any) => {
const prev_dependencies = React.useRef(null);
export const useDeepEffect = (callback: () => void, dependencies?: unknown[]) => {
const prev_dependencies = React.useRef<unknown[] | null>(null);


if (!isDeepEqual(prev_dependencies, dependencies)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import React, { RefObject } from 'react';

export const useHover = (refSetter, should_prevent_bubbling) => {
export const useHover = (refSetter: RefObject<HTMLElement>, should_prevent_bubbling: boolean) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useHover = (refSetter: RefObject<HTMLElement>, should_prevent_bubbling: boolean) => {
export const useHover = (refSetter: RefObject<HTMLElement> | null, should_prevent_bubbling: boolean) => {

const [value, setValue] = React.useState(false);
const default_ref = React.useRef(null);
const ref = refSetter || default_ref;
const ref = refSetter ?? default_ref;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const ref = refSetter ?? default_ref;
const ref = refSetter || default_ref;

@likhith-deriv I would consider leaving it as it is unless we have an existing issue that has to be fixed using ?? 🙂


const handleHoverBegin = () => setValue(true);
const handleHoverFinish = () => setValue(false);
Expand Down Expand Up @@ -40,10 +40,10 @@ export const useHoverCallback = () => {

const handleMouseOver = React.useCallback(() => setValue(true), []);
const handleMouseOut = React.useCallback(() => setValue(false), []);
const ref = React.useRef();
const ref: React.MutableRefObject<HTMLElement | null> = React.useRef(null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const ref: React.MutableRefObject<HTMLElement | null> = React.useRef(null);
const ref = React.useRef<HTMLElement | null>(null);

@likhith-deriv nit suggestion since it's working in the same way, just a bit shorter🙂


const callbackRef = React.useCallback(
node => {
(node: HTMLElement) => {
if (ref.current) {
ref.current.removeEventListener('mouseover', handleMouseOver);
ref.current.removeEventListener('mouseout', handleMouseOut);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

export const useInterval = (callback, delay) => {
const savedCallback = React.useRef();
export const useInterval = (callback: () => void, delay: number) => {
const savedCallback: React.MutableRefObject<any> = React.useRef();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useInterval = (callback: () => void, delay: number) => {
const savedCallback: React.MutableRefObject<any> = React.useRef();
export const useInterval = (callback: () => void, delay: number) => {
const savedCallback = React.useRef<(() => void) | undefined>();
  • a check for undefined will be needed below at line 11 🙂:
    savedCallback.current?.();

React.useEffect(() => {
savedCallback.current = callback;
}, [callback]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import React, { RefObject } from 'react';

export const useOnScroll = (ref, callback) => {
export const useOnScroll = (ref: RefObject<HTMLElement>, callback: () => any) => {
// Allow consumer to prematurely dispose this scroll listener.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useOnScroll = (ref: RefObject<HTMLElement>, callback: () => any) => {
// Allow consumer to prematurely dispose this scroll listener.
export const useOnScroll = (ref: RefObject<HTMLElement>, callback: EventListener) => {
// Allow consumer to prematurely dispose this scroll listener.
const remover = React.useRef<(() => void) | null>(null);

const remover = React.useRef(null);
const remover: React.MutableRefObject<any> = React.useRef(null);
const has_removed = React.useRef(false);

const diposeListener = () => {
Expand All @@ -19,7 +19,7 @@ export const useOnScroll = (ref, callback) => {
ref.current.addEventListener('scroll', callback);

remover.current = () => {
ref.current.removeEventListener('scroll', callback);
ref.current!.removeEventListener('scroll', callback);
};
}

Expand Down
21 changes: 0 additions & 21 deletions packages/components/src/hooks/use-onclickoutside.js

This file was deleted.

30 changes: 30 additions & 0 deletions packages/components/src/hooks/use-onclickoutside.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { RefObject } from 'react';

export const useOnClickOutside = (
ref: RefObject<HTMLElement>,
handler: (event: any) => void,
validationFn: (event: any) => any
) => {
React.useEffect(() => {
const listener = (event: MouseEvent) => {
const path = event.composedPath?.()[0] ?? (event as any).path; //event.path is non-standard and will be deprecated
Copy link

@maryia-deriv maryia-deriv Oct 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useOnClickOutside = (
ref: RefObject<HTMLElement>,
handler: (event: any) => void,
validationFn: (event: any) => any
) => {
React.useEffect(() => {
const listener = (event: MouseEvent) => {
const path = event.composedPath?.()[0] ?? (event as any).path; //event.path is non-standard and will be deprecated
export const useOnClickOutside = (
ref: RefObject<HTMLElement | undefined>,
handler: (event: MouseEvent) => void,
validationFn: (event: MouseEvent) => boolean
) => {
React.useEffect(() => {
const listener = (event: MouseEvent) => {
const path = event.composedPath?.()[0] ?? (event as MouseEvent & { path: HTMLElement }).path; //event.path is non-standard and will be deprecated


// When component is isolated (e.g, iframe, shadow DOM) event.target refers to whole container not the component. path[0] is the node that the event originated from, it does not need to walk the array
if (
ref &&
ref.current &&
!ref.current.contains(event.target as HTMLElement) &&
!ref.current.contains(path as HTMLElement)
) {
if (validationFn && !validationFn(event)) return;
handler(event);
}
};

document.addEventListener('mousedown', listener);

return () => {
document.removeEventListener('mousedown', listener);
};
}, [ref, handler, validationFn]);
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import React from 'react';

export const useLongPress = (
callback = () => {
callback: () => void = () => {
/** empty function */
},
ms = 300
) => {
const [startLongPress, setStartLongPress] = React.useState(false);

const preventDefaults = e => {
const preventDefaults = (e: Event) => {
e.preventDefault();
e.stopPropagation();
};

React.useEffect(() => {
let timer;
let timer: ReturnType<typeof setTimeout> | undefined;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe it better just to use number for types, instead of ReturnType | undefined

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried that. But I get the below error
Screen Shot 2022-10-12 at 8 06 06 AM

if (startLongPress) {
timer = setTimeout(callback, ms);
} else if (timer) {
Expand All @@ -28,13 +28,13 @@ export const useLongPress = (
}, [startLongPress]);

return {
onMouseDown: e => {
onMouseDown: (e: MouseEvent) => {
preventDefaults(e);
setStartLongPress(true);
},
onMouseUp: () => setStartLongPress(false),
onMouseLeave: () => setStartLongPress(false),
onTouchStart: e => {
onTouchStart: (e: TouchEvent) => {
preventDefaults(e);
setStartLongPress(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
export const usePreventIOSZoom = () => {
React.useEffect(() => {
// Fix to prevent iOS from zooming in erratically on quick taps
const preventIOSZoom = event => {
const preventIOSZoom = (event: TouchEvent) => {
if (event.touches.length > 1) {
event.preventDefault();
event.stopPropagation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

export const usePrevious = value => {
export const usePrevious = (value: any) => {
const ref = React.useRef();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const usePrevious = (value: any) => {
const ref = React.useRef();
export const usePrevious = <T>(value: T) => {
const ref = React.useRef<T | undefined>();

React.useEffect(() => {
ref.current = value;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import * as React from 'react';

export const useSafeState = (initial_state, optIsMountedFunc = null) => {
export const useSafeState = <T>(initial_state: T, optIsMountedFunc: () => void) => {
const [state, setState] = React.useState(initial_state);
const is_mounted = React.useRef(false);

React.useLayoutEffect(() => {
is_mounted.current = true;
return () => (is_mounted.current = false);
return () => {
is_mounted.current = false;
};
}, []);

const isMounted = () => {
if (typeof optIsMountedFunc === 'function') {
if (optIsMountedFunc && typeof optIsMountedFunc === 'function') {
return optIsMountedFunc();
}

return is_mounted.current === true;
};

const wrappedSetState = value => {
const wrappedSetState = (value: any) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const wrappedSetState = (value: any) => {
const wrappedSetState = (value: T) => {

if (isMounted()) {
setState(value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

// this hook mimics this.setState({ state: value, ... }, () => callbackFunc());
export const useStateCallback = initial_state => {
export const useStateCallback = <T>(initial_state: T) => {
const [state, setState] = React.useState(initial_state);
const callbackRef = React.useRef(null); // a mutable ref to store existing callback
const callbackRef: React.MutableRefObject<any> = React.useRef(null); // a mutable ref to store existing callback

const setStateCallback = React.useCallback((current_state, cb) => {
const setStateCallback = React.useCallback((current_state: any, cb: (param: any) => void) => {
Copy link

@maryia-deriv maryia-deriv Oct 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const useStateCallback = <T>(initial_state: T) => {
const [state, setState] = React.useState(initial_state);
const callbackRef = React.useRef(null); // a mutable ref to store existing callback
const callbackRef: React.MutableRefObject<any> = React.useRef(null); // a mutable ref to store existing callback
const setStateCallback = React.useCallback((current_state, cb) => {
const setStateCallback = React.useCallback((current_state: any, cb: (param: any) => void) => {
export const useStateCallback = <T>(initial_state: T) => {
const [state, setState] = React.useState(initial_state);
const callbackRef = React.useRef<((param: T) => void) | null>(null); // a mutable ref to store existing callback
const setStateCallback = React.useCallback((current_state: T, cb: (param: T) => void) => {

callbackRef.current = cb; // store the passed callback to the ref
setState(current_state);
}, []);
Expand Down