You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
spa_instat_tv/src/hooks/useObjectState.tsx

36 lines
1.3 KiB

import type { Dispatch, SetStateAction } from 'react'
import { useCallback, useState } from 'react'
import isFunction from 'lodash/isFunction'
type Updater<T> = (prevState: T) => T
const isUpdater = <T extends object>(value: any): value is Updater<T> => (
isFunction(value)
)
/**
* Дженерик для создания типа сеттера, получает тип стейта как параметр
*/
export type SetPartialState<T> = Dispatch<SetStateAction<Partial<T>>>
/**
* Хук на основе useState с возможносьтю мержа стейта как в классовых компонентах
*/
export const useObjectState = <T extends object>(initialState: T) => {
const [state, setState] = useState(initialState)
const setPlayerState: SetPartialState<T> = useCallback((newStateOrUpdater) => {
setState((oldState) => {
const newState = isUpdater(newStateOrUpdater)
? newStateOrUpdater(oldState)
: newStateOrUpdater
// если updater функция вернула старый стейт то и здесь
// возвращаем тот же стейт чтобы избежать лишнего ререндера
if (newState === oldState) return oldState
return { ...oldState, ...newState }
})
}, [])
return [state, setPlayerState] as const
}