Skip to content

Commit

Permalink
main 🧊 add use less, add use performance observer
Browse files Browse the repository at this point in the history
  • Loading branch information
debabin committed Mar 1, 2025
1 parent 4f74080 commit 7391fbd
Show file tree
Hide file tree
Showing 20 changed files with 233 additions and 15 deletions.
2 changes: 2 additions & 0 deletions packages/core/src/bundle/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export * from './useKeyPressEvent/useKeyPressEvent';
export * from './useKeysPressed/useKeysPressed';
export * from './useLastChanged/useLastChanged';
export * from './useLatest/useLatest';
export * from './useLess/useLess';
export * from './useList/useList';
export * from './useLocalStorage/useLocalStorage';
export * from './useLogger/useLogger';
Expand All @@ -75,6 +76,7 @@ export * from './useOtpCredential/useOtpCredential';
export * from './usePageLeave/usePageLeave';
export * from './usePaint/usePaint';
export * from './useParallax/useParallax';
export * from './usePerformanceObserver/usePerformanceObserver';
export * from './usePermission/usePermission';
export * from './usePointerLock/usePointerLock';
export * from './usePostMessage/usePostMessage';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/bundle/hooks/useField/useField.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useRerender } from '../useRerender/useRerender';
*/
export const useField = (params) => {
const initialValue = (params?.initialValue ?? '');
const inputRef = useRef();
const inputRef = useRef(null);
const watchingRef = useRef(false);
const rerender = useRerender();
const [dirty, setDirty] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const useFileDialog = ((...params) => {
const callback = (typeof params[0] === 'function' ? params[0] : undefined);
const options = (callback ? params[0] : params[1]);
const [value, setValue] = useState(null);
const inputRef = useRef();
const inputRef = useRef(null);
const internalCallbackRef = useRef(callback);
internalCallbackRef.current = callback;
const reset = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/bundle/hooks/useFocus/useFocus.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const useFocus = ((...params) => {
const initialValue = options.initialValue ?? false;
const [focused, setFocused] = useState(initialValue);
const internalRef = useRefState();
const elementRef = useRef();
const elementRef = useRef(null);
const focus = () => elementRef.current?.focus();
const blur = () => elementRef.current?.blur();
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const useIntersectionObserver = ((...params) => {
const enabled = options?.enabled ?? true;
const [entry, setEntry] = useState();
const internalRef = useRefState();
const internalOnChangeRef = useRef();
const internalOnChangeRef = useRef(options?.onChange);
internalOnChangeRef.current = options?.onChange;
useEffect(() => {
if (!enabled && !target && !internalRef.state)
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/bundle/hooks/useLess/useLess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect } from 'react';
/**
* @name useLess
* @description - Hook that humorously suggests using it less not for production
* @category Humor
*
* @template Value The type of the value
* @param {Value} [value] The value to be returned
* @returns {Value} The value passed to the hook
*
* @example
* const value = useLess(state);
*/
export const useLess = (value) => {
useEffect(() => {
console.warn("Warning: You forgot to delete the 'useLess' hook.");
}, []);
return value;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef } from 'react';
import { useState } from 'react';
export const getOperatingSystem = () => {
if (typeof window === 'undefined')
return 'undetermined';
Expand Down Expand Up @@ -26,6 +26,6 @@ export const getOperatingSystem = () => {
* const operatingSystem = useOperatingSystem();
*/
export const useOperatingSystem = () => {
const osOperatingSystemRef = useRef(getOperatingSystem());
return osOperatingSystemRef.current;
const [osOperatingSystem] = useState(getOperatingSystem());
return osOperatingSystem;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useRef, useState } from 'react';
/**
* @name usePerformanceObserver
* @description - Hook that allows you to observe performance entries
* @category Sensor
*
* @param {UsePerformanceObserverOptions} options The options for the performance observer
* @param {PerformanceObserverCallback} callback The function to handle performance entries
* @returns {object} An object containing the observer's support status and methods to start and stop the observer
*
* @example
* const { supported, entries, start, stop } = usePerformanceObserver();
*/
export const usePerformanceObserver = (options, callback) => {
const supported = typeof window !== 'undefined' && typeof PerformanceObserver !== 'undefined';
const [entries, setEntries] = useState([]);
const observerRef = useRef(null);
const internalCallback = useRef();
internalCallback.current = callback;
const start = () => {
if (!supported)
return;
const observer = new PerformanceObserver((entryList, observer) => {
setEntries(entryList.getEntries());
internalCallback.current?.(entryList, observer);
});
observer.observe(options);
observerRef.current = observer;
};
const stop = () => {
if (!supported)
return;
observerRef.current?.disconnect();
observerRef.current = null;
};
useEffect(() => {
if (!supported)
return;
if (options.immediate)
start();
return () => {
stop();
};
}, []);
return { supported, entries, start, stop };
};
2 changes: 2 additions & 0 deletions packages/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export * from './useKeyPressEvent/useKeyPressEvent';
export * from './useKeysPressed/useKeysPressed';
export * from './useLastChanged/useLastChanged';
export * from './useLatest/useLatest';
export * from './useLess/useLess';
export * from './useList/useList';
export * from './useLocalStorage/useLocalStorage';
export * from './useLogger/useLogger';
Expand All @@ -75,6 +76,7 @@ export * from './useOtpCredential/useOtpCredential';
export * from './usePageLeave/usePageLeave';
export * from './usePaint/usePaint';
export * from './useParallax/useParallax';
export * from './usePerformanceObserver/usePerformanceObserver';
export * from './usePermission/usePermission';
export * from './usePointerLock/usePointerLock';
export * from './usePostMessage/usePostMessage';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/hooks/useField/useField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const useField = <
): UseFieldReturn<Type> => {
const initialValue = (params?.initialValue ?? '') as Value;

const inputRef = useRef<HTMLInputElement>();
const inputRef = useRef<HTMLInputElement | null>(null);
const watchingRef = useRef(false);
const rerender = useRerender();

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/hooks/useFileDialog/useFileDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const useFileDialog = ((...params: any[]) => {
const options = (callback ? params[0] : params[1]) as UseFileDialogOptions | undefined;

const [value, setValue] = useState<FileList | null>(null);
const inputRef = useRef<HTMLInputElement>();
const inputRef = useRef<HTMLInputElement | null>(null);
const internalCallbackRef = useRef(callback);
internalCallbackRef.current = callback;

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/hooks/useFocus/useFocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const useFocus = ((...params: any[]) => {
const [focused, setFocused] = useState(initialValue);
const internalRef = useRefState<Element>();

const elementRef = useRef<HTMLElement>();
const elementRef = useRef<HTMLElement | null>(null);

const focus = () => elementRef.current?.focus();
const blur = () => elementRef.current?.blur();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const useIntersectionObserver = ((...params: any[]) => {
const [entry, setEntry] = useState<IntersectionObserverEntry>();

const internalRef = useRefState<Element>();
const internalOnChangeRef = useRef<UseIntersectionObserverOptions['onChange']>();
const internalOnChangeRef = useRef<UseIntersectionObserverOptions['onChange']>(options?.onChange);
internalOnChangeRef.current = options?.onChange;

useEffect(() => {
Expand Down
25 changes: 25 additions & 0 deletions packages/core/src/hooks/useLess/useLess.demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useCounter } from '../useCounter/useCounter';
import { useLess } from './useLess';

const Demo = () => {
const counter = useCounter();
const value = useLess(counter.value);

return (
<div>
<div className='rounded-xl bg-amber-50 p-4 text-amber-500'>
<strong>Warning:</strong> This hook is a joke. Please do not use it in production code!
</div>

<p>
Useless value is <code>{value}</code>
</p>

<button className='button' type='button' onClick={() => counter.inc()}>
Increment
</button>
</div>
);
};

export default Demo;
17 changes: 17 additions & 0 deletions packages/core/src/hooks/useLess/useLess.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { renderHook } from '@testing-library/react';

import { useLess } from './useLess';

it('Should use less', () => {
const { result } = renderHook(() => useLess('value'));

expect(result.current).toBe('value');
});

it('Should log a warning when useLess is used', () => {
const mockConsoleWarn = vi.spyOn(console, 'warn');
renderHook(() => useLess());

expect(mockConsoleWarn).toHaveBeenCalledWith("Warning: You forgot to delete the 'useLess' hook.");
mockConsoleWarn.mockRestore();
});
21 changes: 21 additions & 0 deletions packages/core/src/hooks/useLess/useLess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect } from 'react';

/**
* @name useLess
* @description - Hook that humorously suggests using it less not for production
* @category Humor
*
* @template Value The type of the value
* @param {Value} [value] The value to be returned
* @returns {Value} The value passed to the hook
*
* @example
* const value = useLess(state);
*/
export const useLess = (value?: any) => {
useEffect(() => {
console.warn("Warning: You forgot to delete the 'useLess' hook.");
}, []);

return value;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useMutationObserver } from './useMutationObserver';

export const Demo = () => {
const [observed, setObserved] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);
const buttonRef = useRef<HTMLButtonElement | null>(null);

useMutationObserver(
buttonRef,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef } from 'react';
import { useState } from 'react';

/** The operating system type */
export type OperatingSystem = 'android' | 'ios' | 'linux' | 'macos' | 'undetermined' | 'windows';
Expand Down Expand Up @@ -28,6 +28,6 @@ export const getOperatingSystem = (): OperatingSystem => {
* const operatingSystem = useOperatingSystem();
*/
export const useOperatingSystem = () => {
const osOperatingSystemRef = useRef<OperatingSystem>(getOperatingSystem());
return osOperatingSystemRef.current;
const [osOperatingSystem] = useState<OperatingSystem>(getOperatingSystem());
return osOperatingSystem;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { usePerformanceObserver } from './usePerformanceObserver';

const Demo = () => {
const performance = usePerformanceObserver(
{ entryTypes: ['paint'], immediate: true }
);

const refresh = () => window.location.reload();

return (
<div>
<p>Performance entries:</p>
<ul>
{performance.entries.map((entry, index) => (
<li key={index}>
{entry.name}:{' '}
<code>
{entry.startTime} - {entry.duration}ms
</code>
</li>
))}
</ul>
<button onClick={refresh}>Refresh</button>
</div>
);
};

export default Demo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useEffect, useRef, useState } from 'react';

/** The use performance observer options type */
export type UsePerformanceObserverOptions = PerformanceObserverInit & {
/** Whether to start the observer immediately */
immediate?: boolean;
};

/**
* @name usePerformanceObserver
* @description - Hook that allows you to observe performance entries
* @category Sensor
*
* @param {UsePerformanceObserverOptions} options The options for the performance observer
* @param {PerformanceObserverCallback} callback The function to handle performance entries
* @returns {object} An object containing the observer's support status and methods to start and stop the observer
*
* @example
* const { supported, entries, start, stop } = usePerformanceObserver();
*/
export const usePerformanceObserver = (
options: UsePerformanceObserverOptions,
callback?: PerformanceObserverCallback
) => {
const supported = typeof window !== 'undefined' && typeof PerformanceObserver !== 'undefined';
const [entries, setEntries] = useState<PerformanceEntry[]>([]);

const observerRef = useRef<PerformanceObserver | null>(null);
const internalCallback = useRef<PerformanceObserverCallback | null>();
internalCallback.current = callback;

const start = () => {
if (!supported) return;
const observer = new PerformanceObserver((entryList, observer) => {
setEntries(entryList.getEntries());
internalCallback.current?.(entryList, observer);
});
observer.observe(options);
observerRef.current = observer;
};

const stop = () => {
if (!supported) return;
observerRef.current?.disconnect();
observerRef.current = null;
};

useEffect(() => {
if (!supported) return;
if (options.immediate) start();

return () => {
stop();
};
}, []);

return { supported, entries, start, stop };
};

0 comments on commit 7391fbd

Please sign in to comment.