Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
44 changes: 38 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ A lightweight library that provides two essential custom hooks for your react or
- **`useInterval`**: Set up recurring functions at specified intervals.
- **`useTimeout`**: Delay execution of a function for a specified time.
- **`useDebouncedValue`**: Debounce a value, updating it after a specified delay.
- **`useCopyToClipboard`**: Copies text to clipboard

## Installation

Expand All @@ -22,7 +23,7 @@ npm install @shurutech/react-hook-tools

#### Syntax:

```
```jsx
useInterval(()=>{
// functionality
},time)
Expand All @@ -31,7 +32,7 @@ Note: Time will in milliseconds ( > 0 ) if you need to run interval, and undefin

#### Example

```
```jsx
import { useInterval } from '@shurutech/react-hook-tools';

const IntervalComponent = () => {
Expand All @@ -47,7 +48,7 @@ const IntervalComponent = () => {

#### Syntax:

```
```jsx
useTimeout(()=>{
// functionality
},time)
Expand All @@ -56,7 +57,7 @@ Note: Time will in milliseconds ( > 0 ) if you need to run interval, and undefin

#### Example

```
```jsx
import { useTimeout } from '@shurutech/react-hook-tools';

const TimerComponent = () => {
Expand All @@ -72,13 +73,13 @@ const TimerComponent = () => {

#### Syntax:

```
```jsx
const debouncedValue = useDebouncedValue(value, delay);
```

#### Example

```
```jsx
import { useDebouncedValue } from '@shurutech/react-hook-tools';

const SearchComponent = () => {
Expand All @@ -103,6 +104,37 @@ const SearchComponent = () => {
};
```

### useCopyToClipboard:

#### Syntax:

```jsx
const [copiedText, copyFunction] = useCopyToClipboard()
```

#### Example

```jsx
import { useCopyToClipboard } from '@shurutech/react-hook-tools';

const CopyComponent = () => {
const [copiedText, copyFunction] = useCopyToClipboard()

const handleCopy = async () => {
const copyStatus = await copyFunction("Hello, World!")

if(copyStatus)
console.log("Text copied successfully!")
else
console.log("Copy failed!")
}

return (
<button onClick={handleCopy}>Copy Text</button>
);
};
```

## How to Contribute
1. Fork this repository to your GitHub account and clone it locally.

Expand Down
58 changes: 58 additions & 0 deletions src/hooks/useCopyToClipboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useCallback, useState } from "react";

/**
*
* @description Custom hook that copies text to the clipboard using the `Clipboard API`.
*
*
* @typedef {string | null} CopiedValue
* @typedef {(text: string) => Promise<boolean>} CopyFunction
*
* @returns {[CopiedValue, CopyFunction]}
*
* @example
* ```jsx
*
* const [copiedText, copyFunction] = useCopyToClipboard()
*
* const handleCopy = async () => {
* const copyStatus = await copyFunction("Hello, World!")
* if(copyStatus) console.log("Text copied successfully!")
* else console.log("Copy failed!")
* }
*
* <button onClick={handleCopy}>Copy Text</button>
* ```
*/
export function useCopyToClipboard() {
const [copiedText, setCopiedText] = useState(null);

/**
* @description Function that copies text to the clipboard.
* @type {CopyFunction}
*/
const copyFunction = useCallback(
async (text) => {
if (!navigator.clipboard) {
// Clipboard API not available
console.warn("Clipboard API not available");
return false;
}

try {
await navigator.clipboard.writeText(text);
setCopiedText(text);

return true;
} catch (error) {
console.warn("Copy to clipboard failed", error);
setCopiedText(null);

return false;
}
},
[]
);

return [copiedText, copyFunction];
}
2 changes: 1 addition & 1 deletion src/hooks/useDebouncedValue.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useEffect, useState } from 'react';

export function useDebouncedValue(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
Expand Down
27 changes: 26 additions & 1 deletion src/hooks/useInterval.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import { useEffect, useRef } from 'react'
import { useEffect, useRef } from 'react';
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';

/**
* @description Custom hook that creates an interval that invokes a callback function at a specified delay using the `setInterval` API.
*
*
* @param {() => void} callback The function to be invoked at each interval.
* @param {number | null} delay The time, in milliseconds, between each invocation of the callback. Use null to clear the interval.
*
* @returns {void} This hook does not return anything.
*
* @example
* ```jsx
* const [count, setCount] = useState(0)
* const counter = () => {
* setCount(x => x + 1)
* }
* // Increment the count every 2 seconds
* useInterval(counter, 2000)
* ```
*/
export function useInterval(callback, delay) {
const savedCallback = useRef(callback)

// Remember the latest callback if it changes.
useIsomorphicLayoutEffect(() => {
savedCallback.current = callback;
}, [callback]);

useEffect(() => {
if (delay === null) {
return
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/useIsomorphicLayoutEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { useEffect, useLayoutEffect } from 'react'

export const useIsomorphicLayoutEffect =
typeof window !== 'undefined' ? useLayoutEffect : useEffect
42 changes: 33 additions & 9 deletions src/hooks/useTimeout.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
import { useEffect, useRef } from 'react'
import { useEffect, useRef } from "react";
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";

/**
* @description Custom hook that handles timeouts in React components using the setTimeout API.
*
*
* @param {() => void} callback The function to be executed when the timeout elapses.
* @param {number | null} delay The duration (in milliseconds) for the timeout. Set to null to clear the timeout.
*
* @returns {void} This hook does not return anything.
*
* @example
* ```jsx
* const [visible, setVisible] = useState(true)
* const hide = () => {
* setVisible(false)
* }
* useTimeout(hide, 5000)
* ```
*/
export function useTimeout(callback, delay) {
const savedCallback = useRef(callback)
const savedCallback = useRef(callback);

// Remember the latest callback if it changes.
useIsomorphicLayoutEffect(() => {
savedCallback.current = callback;
}, [callback]);

useEffect(() => {
if (!delay && delay !== 0) {
return
return;
}

const id = setTimeout(() => {
savedCallback.current()
}, delay)
savedCallback.current();
}, delay);

return () => {
clearTimeout(id)
}
}, [delay])
}
clearTimeout(id);
};
}, [delay]);
}
9 changes: 5 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useInterval } from "./hooks/useInterval";
import { useTimeout } from "./hooks/useTimeout";
import { useDebouncedValue } from "./hooks/useDebouncedValue";
export { useCopyToClipboard } from './hooks/useCopyToClipboard';
export { useDebouncedValue } from "./hooks/useDebouncedValue";
export { useInterval } from "./hooks/useInterval";
export { useIsomorphicLayoutEffect } from "./hooks/useIsomorphicLayoutEffect";
export { useTimeout } from "./hooks/useTimeout";

export {useInterval,useTimeout,useDebouncedValue}