Skip to content

Commit 5ba6dd3

Browse files
committed
main 🧊 fix internal ref
1 parent b151a79 commit 5ba6dd3

File tree

14 files changed

+154
-177
lines changed

14 files changed

+154
-177
lines changed

‎src/hooks/useClickOutside/useClickOutside.demo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { useClickOutside } from './useClickOutside';
55
const Demo = () => {
66
const counter = useCounter();
77

8-
const ref = useClickOutside<HTMLDivElement>(() => {
8+
const clickOutsideRef = useClickOutside<HTMLDivElement>(() => {
99
console.log('click outside');
1010
counter.inc();
1111
});
1212

1313
return (
1414
<div
15-
ref={ref}
15+
ref={clickOutsideRef}
1616
style={{
1717
width: 200,
1818
height: 200,

‎src/hooks/useClickOutside/useClickOutside.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import type { RefObject } from 'react';
2-
import { useEffect, useRef } from 'react';
3-
4-
import { useRerender } from '../useRerender/useRerender';
2+
import { useEffect, useRef, useState } from 'react';
53

64
/** The use click outside target element type */
75
type UseClickOutsideTarget = RefObject<Element | null | undefined> | (() => Element) | Element;
@@ -53,19 +51,18 @@ export type UseClickOutside = {
5351
* const ref = useClickOutside<HMLDiTvElement>(() => console.log('click outside'));
5452
*/
5553
export const useClickOutside = ((...params: any[]) => {
56-
const rerender = useRerender();
5754
const target = (typeof params[1] === 'undefined' ? undefined : params[0]) as
5855
| UseClickOutsideTarget
5956
| UseClickOutsideTarget[]
6057
| undefined;
6158
const callback = (params[1] ? params[1] : params[0]) as (event: Event) => void;
6259

63-
const internalRef = useRef<Element>();
60+
const [internalRef, setInternalRef] = useState<Element>();
6461
const internalCallbackRef = useRef(callback);
6562
internalCallbackRef.current = callback;
6663

6764
useEffect(() => {
68-
if (!target && !internalRef.current) return;
65+
if (!target && !internalRef) return;
6966
const handler = (event: Event) => {
7067
if (Array.isArray(target)) {
7168
if (!target.length) return;
@@ -80,7 +77,7 @@ export const useClickOutside = ((...params: any[]) => {
8077
return;
8178
}
8279

83-
const element = target ? getElement(target) : internalRef.current;
80+
const element = target ? getElement(target) : internalRef;
8481

8582
if (element && !element.contains(event.target as Node)) {
8683
internalCallbackRef.current(event);
@@ -94,13 +91,8 @@ export const useClickOutside = ((...params: any[]) => {
9491
document.removeEventListener('mousedown', handler);
9592
document.removeEventListener('touchstart', handler);
9693
};
97-
}, [internalRef.current, target]);
94+
}, [internalRef, target]);
9895

9996
if (target) return;
100-
return (node: Element) => {
101-
if (!internalRef.current) {
102-
internalRef.current = node;
103-
rerender.update();
104-
}
105-
};
97+
return setInternalRef;
10698
}) as UseClickOutside;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { useCssVar } from './useCssVar';
2+
3+
const Demo = () => {
4+
const counter = useCssVar('--count');
5+
6+
return (
7+
<p>
8+
Count: <code>{counter}</code>
9+
</p>
10+
);
11+
};
12+
13+
export default Demo;

‎src/hooks/useCssVar/useCssVar.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useState } from 'react';
2+
3+
import { useMutationObserver } from '../useMutationObserver';
4+
5+
/**
6+
* @name useCssVar
7+
* @description - Hook that returns the value of a CSS variable
8+
* @category Utilities
9+
*
10+
* @param {string} key The CSS variable key
11+
* @param {string} initialValue The initial value of the CSS variable
12+
* @returns {string} The value of the CSS variable
13+
*
14+
* @example
15+
* const value = useCssVar('color', 'red');
16+
*/
17+
export const useCssVar = (key: string, initialValue: string) => {
18+
const [value, setValue] = useState(initialValue);
19+
20+
const updateCssVar = () => {
21+
const value = window
22+
.getComputedStyle(window?.document?.documentElement)
23+
.getPropertyValue(key)
24+
?.trim();
25+
26+
setValue(value ?? initialValue);
27+
};
28+
29+
useMutationObserver(updateCssVar, {
30+
attributeFilter: ['style', 'class']
31+
});
32+
33+
return value;
34+
};

‎src/hooks/useEventListener/useEventListener.demo.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ const Demo = () => {
99
}
1010
);
1111

12-
useEventListener(window, 'click', (event) => console.log('@click 2', event.target), {
13-
passive: true
14-
});
15-
1612
return (
1713
<div
1814
id='content'

‎src/hooks/useEventListener/useEventListener.ts

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { RefObject } from 'react';
2-
import { useEffect, useRef } from 'react';
2+
import { useEffect, useState } from 'react';
3+
4+
import { getElement } from '@/utils/helpers';
35

46
import { useEvent } from '../useEvent/useEvent';
57

@@ -10,18 +12,6 @@ export type UseEventListenerTarget =
1012
| Window
1113
| Document;
1214

13-
const getElement = (target: UseEventListenerTarget) => {
14-
if (typeof target === 'function') {
15-
return target();
16-
}
17-
18-
if (target instanceof Element || target instanceof Window || target instanceof Document) {
19-
return target;
20-
}
21-
22-
return target.current;
23-
};
24-
2515
export type UseEventListenerOptions = boolean | AddEventListenerOptions;
2616

2717
export type UseEventListenerReturn<Target extends UseEventListenerTarget> = RefObject<Target>;
@@ -78,20 +68,21 @@ export const useEventListener = ((...params: any[]) => {
7868
const listener = (target ? params[2] : params[1]) as (...arg: any[]) => void | undefined;
7969
const options: UseEventListenerOptions | undefined = target ? params[3] : params[2];
8070

81-
const internalRef = useRef<Element | Document | Window>(null);
71+
const [internalRef, setInternalRef] = useState<Element>();
8272
const internalListener = useEvent(listener);
8373

8474
useEffect(() => {
75+
if (!target && !internalRef) return;
8576
const callback = (event: Event) => internalListener(event);
86-
const element = target ? getElement(target) : internalRef.current;
77+
const element = target ? getElement(target) : internalRef;
8778
if (element) {
8879
events.forEach((event) => element.addEventListener(event, callback, options));
8980
return () => {
9081
events.forEach((event) => element.removeEventListener(event, callback, options));
9182
};
9283
}
93-
}, [target, event, options]);
84+
}, [target, internalRef, event, options]);
9485

9586
if (target) return;
96-
return internalRef;
87+
return setInternalRef;
9788
}) as UseEventListener;

‎src/hooks/useInfiniteScroll/useInfiniteScroll.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { RefObject } from 'react';
22
import { useEffect, useRef, useState } from 'react';
33

44
import { useEvent } from '../useEvent/useEvent';
5-
import { useRerender } from '../useRerender/useRerender';
65

76
/** The use infinite scroll target element type */
87
export type UseInfiniteScrollTarget = RefObject<Element | null> | (() => Element) | Element;
@@ -71,7 +70,6 @@ export type UseInfiniteScroll = {
7170
* const isLoading = useInfiniteScroll(ref, () => console.log('infinite scroll'));
7271
*/
7372
export const useInfiniteScroll = ((...params) => {
74-
const rerender = useRerender();
7573
const target = params[1] instanceof Function ? (params[0] as UseInfiniteScrollTarget) : undefined;
7674
const callback = params[1] instanceof Function ? params[1] : (params[0] as () => void);
7775
const options = (
@@ -82,7 +80,7 @@ export const useInfiniteScroll = ((...params) => {
8280
const distance = options?.distance ?? 10;
8381

8482
const [isLoading, setIsLoading] = useState(false);
85-
const internalRef = useRef<Element>();
83+
const [internalRef, setInternalRef] = useState<Element>();
8684
const internalCallbackRef = useRef(callback);
8785
internalCallbackRef.current = callback;
8886

@@ -108,24 +106,20 @@ export const useInfiniteScroll = ((...params) => {
108106
});
109107

110108
useEffect(() => {
111-
const element = target ? getElement(target) : internalRef.current;
109+
if (!target && !internalRef) return;
110+
const element = target ? getElement(target) : internalRef;
112111
if (!element) return;
113112

114113
element.addEventListener('scroll', onLoadMore);
115114

116115
return () => {
117116
element.removeEventListener('scroll', onLoadMore);
118117
};
119-
}, [internalRef.current, target, direction, distance]);
118+
}, [internalRef, target, direction, distance]);
120119

121120
if (target) return isLoading;
122121
return {
123-
ref: (node: Element) => {
124-
if (!internalRef.current) {
125-
internalRef.current = node;
126-
rerender.update();
127-
}
128-
},
122+
ref: setInternalRef,
129123
isLoading
130124
};
131125
}) as UseInfiniteScroll;

‎src/hooks/useIntersectionObserver/useIntersectionObserver.ts

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { RefObject } from 'react';
22
import { useEffect, useRef, useState } from 'react';
33

4-
import { useRerender } from '../useRerender/useRerender';
4+
import { getElement } from '@/utils/helpers';
55

66
/** The intersection observer target element type */
77
export type UseIntersectionObserverTarget =
@@ -16,32 +16,6 @@ export interface UseIntersectionObserverOptions extends Omit<IntersectionObserve
1616
root?: IntersectionObserverInit['root'] | RefObject<Element | null | undefined>;
1717
}
1818

19-
const getTargetElement = (target: UseIntersectionObserverTarget) => {
20-
if (typeof target === 'function') {
21-
return target();
22-
}
23-
24-
if (target instanceof Element) {
25-
return target;
26-
}
27-
28-
return target.current;
29-
};
30-
31-
const getRootElement = (root: UseIntersectionObserverOptions['root']) => {
32-
if (!root) return document;
33-
34-
if (root instanceof Element) {
35-
return root;
36-
}
37-
38-
if (root instanceof Document) {
39-
return root;
40-
}
41-
42-
return root.current;
43-
};
44-
4519
/** The intersection observer return type */
4620
export interface UseIntersectionObserverReturn {
4721
inView: boolean;
@@ -87,7 +61,6 @@ export type UseIntersectionObserver = {
8761
* const { entry, inView } = useIntersectionObserver(ref);
8862
*/
8963
export const useIntersectionObserver = ((...params: any[]) => {
90-
const rerender = useRerender();
9164
const target = (
9265
typeof params[0] === 'object' && !('current' in params[0]) ? undefined : params[0]
9366
) as UseIntersectionObserverTarget | undefined;
@@ -96,13 +69,13 @@ export const useIntersectionObserver = ((...params: any[]) => {
9669

9770
const [entry, setEntry] = useState<IntersectionObserverEntry>();
9871

99-
const internalRef = useRef<Element>();
72+
const [internalRef, setInternalRef] = useState<Element>();
10073
const internalOnChangeRef = useRef<UseIntersectionObserverOptions['onChange']>();
10174
internalOnChangeRef.current = options?.onChange;
10275

10376
useEffect(() => {
104-
if (!enabled || !internalRef.current) return;
105-
const element = target ? getTargetElement(target) : internalRef.current;
77+
if (!enabled || !internalRef) return;
78+
const element = target ? getElement(target) : internalRef;
10679
if (!element) return;
10780

10881
const observer = new IntersectionObserver(
@@ -112,32 +85,20 @@ export const useIntersectionObserver = ((...params: any[]) => {
11285
},
11386
{
11487
...options,
115-
root: getRootElement(options?.root)
88+
root: options?.root ? (getElement(options?.root) as Element | Document) : document
11689
}
11790
);
11891

119-
observer.observe(element);
92+
observer.observe(element as Element);
12093

12194
return () => {
12295
observer.disconnect();
12396
};
124-
}, [
125-
internalRef.current,
126-
target,
127-
options?.rootMargin,
128-
options?.threshold,
129-
options?.root,
130-
enabled
131-
]);
97+
}, [target, internalRef, options?.rootMargin, options?.threshold, options?.root, enabled]);
13298

13399
if (target) return { entry, inView: !!entry?.isIntersecting };
134100
return {
135-
ref: (node: Element) => {
136-
if (!internalRef.current) {
137-
internalRef.current = node;
138-
rerender.update();
139-
}
140-
},
101+
ref: setInternalRef,
141102
entry,
142103
inView: !!entry?.isIntersecting
143104
};

‎src/hooks/useLongPress/useLongPress.demo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useLongPress } from './useLongPress';
44

55
const Demo = () => {
66
const counter = useCounter();
7-
const [longPressedRef, longPressing] = useLongPress<HTMLButtonElement>(() => counter.inc());
7+
const [bind, longPressing] = useLongPress(() => counter.inc());
88

99
return (
1010
<>
@@ -14,7 +14,7 @@ const Demo = () => {
1414
<p>
1515
Clicked: <code>{counter.value}</code>
1616
</p>
17-
<button type='button' ref={longPressedRef}>
17+
<button type='button' {...bind}>
1818
Long press
1919
</button>
2020
</>

0 commit comments

Comments
 (0)