diff --git a/packages/core/useClickOutside/index.ts b/packages/core/useClickOutside/index.ts index 6736c38..acc881b 100644 --- a/packages/core/useClickOutside/index.ts +++ b/packages/core/useClickOutside/index.ts @@ -1,5 +1,6 @@ import type { MaybeRef } from '@react-hooks-library/shared' import { unRef } from '@react-hooks-library/shared' +import { useCallback } from 'react' import { _window } from '../_ssr.config' import { useEventListener } from '../useEventListener' @@ -35,14 +36,17 @@ export function useClickOutside< ) { const { event = 'pointerdown' } = options - const listener = (event: ClickOutsideEvents[E]) => { - const el = unRef(target) - if (!el) return + const listener = useCallback( + (event: ClickOutsideEvents[E]) => { + const el = unRef(target) + if (!el) return - if (el === event.target || event.composedPath().includes(el)) return + if (el === event.target || event.composedPath().includes(el)) return - handler(event) - } + handler(event) + }, + [handler, target] + ) return useEventListener(_window, event, listener, { passive: true }) } diff --git a/packages/core/useKeyStroke/index.ts b/packages/core/useKeyStroke/index.ts index 68e664a..faa707f 100644 --- a/packages/core/useKeyStroke/index.ts +++ b/packages/core/useKeyStroke/index.ts @@ -1,4 +1,5 @@ -import { isString, MaybeRef } from '@react-hooks-library/shared' +import { MaybeRef } from '@react-hooks-library/shared' +import { useCallback } from 'react' import { _window } from '../_ssr.config' import { useEventListener } from '../useEventListener' @@ -59,12 +60,14 @@ export function useKeyStroke( code = false } = options - const listener = (e: KeyboardEvent) => { - const eventKey = code ? e.code : e.key + const listener = useCallback( + (e: KeyboardEvent) => { + const eventKey = code ? e.code : e.key - if (isString(keys)) keys = [keys] - if (keys.includes(eventKey)) handler(e) - } + keys.includes(eventKey) && handler(e) + }, + [code, handler, keys] + ) return useEventListener(target, eventName, listener, { passive }) } diff --git a/packages/core/useLocalStorage/index.ts b/packages/core/useLocalStorage/index.ts index 3991b68..32262be 100644 --- a/packages/core/useLocalStorage/index.ts +++ b/packages/core/useLocalStorage/index.ts @@ -1,5 +1,4 @@ -import { isFunction } from '@react-hooks-library/shared' -import type { Dispatch, SetStateAction } from 'react' +import { useCallback } from 'react' import { useState } from 'react' import { useMount } from '../useMount' @@ -33,7 +32,7 @@ export function useLocalStorage( key: string, initialValue: T, options?: UseLocalStorageOptions -): [T, Dispatch>] { +): [T, (value: T) => void] { const [storedValue, setStoredValue] = useState(initialValue) const { deserialize = JSON.parse, serialize = JSON.stringify } = options || {} @@ -46,16 +45,17 @@ export function useLocalStorage( } }) - const setValue: Dispatch> = (value) => { - try { - const valueToStore = isFunction(value) ? value(storedValue) : value - - setStoredValue(valueToStore) - localStorage.setItem(key, serialize(valueToStore)) - } catch (error) { - console.error(error) - } - } + const setValue = useCallback( + (value: T) => { + try { + localStorage.setItem(key, serialize(value)) + setStoredValue(value) + } catch (error) { + console.error(error) + } + }, + [key, serialize] + ) return [storedValue, setValue] } diff --git a/packages/core/useMediaStream/index.ts b/packages/core/useMediaStream/index.ts index 6c4adec..be4caad 100644 --- a/packages/core/useMediaStream/index.ts +++ b/packages/core/useMediaStream/index.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { _navigator } from '../_ssr.config' import { useIsSupported } from '../useIsSupported' @@ -50,16 +50,19 @@ export function useMediaStream(options: UseMediaStreamOptions = {}) { const [isAudioMuted, setAudioMuted] = useState(false) const [isVideoMuted, setVideoMuted] = useState(false) - function getDeviceOptions(device: string | undefined | false | 'none') { - if (device === 'none' || device === false) return false - if (device === null) return true + const getDeviceOptions = useCallback( + (device: string | undefined | false | 'none') => { + if (device === 'none' || device === false) return false + if (device === null) return true - return { - deviceId: device - } - } + return { + deviceId: device + } + }, + [] + ) - async function play() { + const play = useCallback(async () => { if (!isSupported || stream.current) return stream.current = @@ -70,48 +73,48 @@ export function useMediaStream(options: UseMediaStreamOptions = {}) { setPlaying(true) return stream.current - } + }, [audioDeviceId, getDeviceOptions, isSupported, videoDeviceId]) - async function stop() { + const stop = useCallback(() => { setPlaying(false) stream.current?.getTracks().forEach((t) => t.stop()) stream.current = null - } + }, []) - async function restart() { + const restart = useCallback(async () => { stop() return await play() - } + }, [play, stop]) - function muteAudio() { + const muteAudio = useCallback(() => { setAudioMuted(true) stream.current?.getAudioTracks().forEach((t) => (t.enabled = false)) - } + }, []) - function unMuteAudio() { + const unMuteAudio = useCallback(() => { setAudioMuted(false) stream.current?.getAudioTracks().forEach((t) => (t.enabled = true)) - } + }, []) - function muteVideo() { + const muteVideo = useCallback(() => { setVideoMuted(true) stream.current?.getVideoTracks().forEach((t) => (t.enabled = false)) - } + }, []) - function unMuteVideo() { + const unMuteVideo = useCallback(() => { setVideoMuted(false) stream.current?.getVideoTracks().forEach((t) => (t.enabled = true)) - } + }, []) - function pause() { + const pause = useCallback(() => { muteAudio() muteVideo() - } + }, [muteAudio, muteVideo]) - function resume() { + const resume = useCallback(() => { unMuteAudio() unMuteVideo() - } + }, [unMuteAudio, unMuteVideo]) useEffect(() => { if (!ref.current) return @@ -121,7 +124,7 @@ export function useMediaStream(options: UseMediaStreamOptions = {}) { useEffect(() => { if (autoSwitch && stream.current) restart() - }, [videoDeviceId, audioDeviceId, autoSwitch]) + }, [videoDeviceId, audioDeviceId, autoSwitch, restart]) return { isSupported, diff --git a/packages/core/useScreenShare/index.ts b/packages/core/useScreenShare/index.ts index 90806e8..fddffcb 100644 --- a/packages/core/useScreenShare/index.ts +++ b/packages/core/useScreenShare/index.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { _navigator } from '../_ssr.config' import { useIsSupported } from '../useIsSupported' @@ -36,7 +36,7 @@ export function useScreenShare(options: UseScreenShareOptions = {}) { const [isPlaying, setPlaying] = useState(false) - async function play() { + const play = useCallback(async () => { if (!isSupported || !ref.current) return stream.current = @@ -48,13 +48,13 @@ export function useScreenShare(options: UseScreenShareOptions = {}) { setPlaying(true) return stream.current - } + }, [audio, isSupported, video]) - async function stop() { + const stop = useCallback(() => { stream.current?.getTracks().forEach((t) => t.stop()) stream.current = null setPlaying(false) - } + }, []) useEffect(() => { if (!ref.current) return @@ -63,7 +63,7 @@ export function useScreenShare(options: UseScreenShareOptions = {}) { // Handle os native stop screen sharing buttons stream.current?.getVideoTracks()[0].addEventListener('ended', stop) - }, [isPlaying]) + }, [isPlaying, stop]) return { isSupported, diff --git a/packages/core/useSessionStorage/index.ts b/packages/core/useSessionStorage/index.ts index eda1bb3..749c8d3 100644 --- a/packages/core/useSessionStorage/index.ts +++ b/packages/core/useSessionStorage/index.ts @@ -1,5 +1,5 @@ import { isFunction } from '@react-hooks-library/shared' -import type { Dispatch, SetStateAction } from 'react' +import { Dispatch, SetStateAction, useCallback } from 'react' import { useState } from 'react' import { useMount } from '../useMount' @@ -33,7 +33,7 @@ export function useSessionStorage( key: string, initialValue: T, options?: UseSessionStorageOptions -): [T, Dispatch>] { +): [T, (value: T) => void] { const [storedValue, setStoredValue] = useState(initialValue) const { deserialize = JSON.parse, serialize = JSON.stringify } = options || {} @@ -46,16 +46,17 @@ export function useSessionStorage( } }) - const setValue: Dispatch> = (value) => { - try { - const valueToStore = isFunction(value) ? value(storedValue) : value - - setStoredValue(valueToStore) - sessionStorage.setItem(key, serialize(valueToStore)) - } catch (error) { - console.error(error) - } - } + const setValue = useCallback( + (value: T) => { + try { + setStoredValue(value) + sessionStorage.setItem(key, serialize(value)) + } catch (error) { + console.error(error) + } + }, + [key, serialize] + ) return [storedValue, setValue] } diff --git a/packages/core/useStateHistory/index.ts b/packages/core/useStateHistory/index.ts index 79e45d3..58b0a18 100644 --- a/packages/core/useStateHistory/index.ts +++ b/packages/core/useStateHistory/index.ts @@ -1,5 +1,5 @@ import { isFunction } from '@react-hooks-library/shared' -import { useRef, useState } from 'react' +import { useCallback, useRef, useState } from 'react' type UseStateHistoryOptions = { /** @@ -34,27 +34,30 @@ export function useStateHistory( const redoHistory = useRef([]) const redoAllowed = useRef(false) - const push = (value: T) => { - if (actionHistory.current.length < maxHistory) { - actionHistory.current.push(value) - } else { - actionHistory.current = [...actionHistory.current.slice(1), value] - lastSaved.current = actionHistory.current[0] - } + const push = useCallback( + (value: T) => { + if (actionHistory.current.length < maxHistory) { + actionHistory.current.push(value) + } else { + actionHistory.current = [...actionHistory.current.slice(1), value] + lastSaved.current = actionHistory.current[0] + } - redoAllowed.current = false - setState(value) - } + redoAllowed.current = false + setState(value) + }, + [maxHistory] + ) - const redo = () => { + const redo = useCallback(() => { if (!(redoHistory.current.length && redoAllowed.current)) return const lastUndoState = redoHistory.current.pop() lastUndoState && push(lastUndoState) redoAllowed.current = true - } + }, [push]) - const undo = () => { + const undo = useCallback(() => { if (actionHistory.current.length < 1) return const lastState = actionHistory.current.pop() @@ -64,12 +67,12 @@ export function useStateHistory( prev ? setState(prev) : setState(lastSaved.current) rerender({}) redoAllowed.current = true - } + }, [rerender]) - const reset = () => { + const reset = useCallback(() => { setState(actionHistory.current[0]) actionHistory.current = [actionHistory.current[0]] - } + }, []) return { state, diff --git a/packages/core/useToggle/index.ts b/packages/core/useToggle/index.ts index 3e3246c..679f35b 100644 --- a/packages/core/useToggle/index.ts +++ b/packages/core/useToggle/index.ts @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useCallback, useState } from 'react' /** * A state toggle hook @@ -11,9 +11,11 @@ import { useState } from 'react' export function useToggle(defaultValue = false) { const [bool, setBool] = useState(defaultValue) - const toggle = () => setBool((s) => !s) - const setTrue = () => setBool(true) - const setFalse = () => setBool(false) + const toggle = useCallback(() => setBool((s) => !s), []) + + const setTrue = useCallback(() => setBool(true), []) + + const setFalse = useCallback(() => setBool(false), []) return { bool, toggle, setTrue, setFalse } } diff --git a/packages/core/useUnMount/index.ts b/packages/core/useUnMount/index.ts index 6d2f31e..0be54d1 100644 --- a/packages/core/useUnMount/index.ts +++ b/packages/core/useUnMount/index.ts @@ -9,5 +9,5 @@ import { useEffect } from 'react' export function useUnMount(func: Fn) { useEffect(() => { return func - }, []) + }, [func]) }