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