import type { Dispatch, SetStateAction } from 'react' import { useCallback, useState } from 'react' import isFunction from 'lodash/isFunction' type Updater = (prevState: T) => T const isUpdater = (value: any): value is Updater => ( isFunction(value) ) /** * Дженерик для создания типа сеттера, получает тип стейта как параметр */ export type SetPartialState = Dispatch>> /** * Хук на основе useState с возможносьтю мержа стейта как в классовых компонентах */ export const useObjectState = (initialState: T) => { const [state, setState] = useState(initialState) const setPlayerState: SetPartialState = 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 }