import { useEffect, useRef, useState } from 'react'; import { InitializerOrValue, isInitializer } from '../utils/is-initializer'; import { isDefined } from '../utils/type-utils'; import { isBrowser, useIsomorphicLayoutEffect, } from '../utils/use-isomorphic-layout-effect'; import { createStateWire } from './create-state-wire'; import { StateWire } from './state-wire'; const create = ( upLink: StateWire | null | undefined, initialValue: InitializerOrValue, ) => { return createStateWire( upLink || {}, isDefined(initialValue) ? isInitializer(initialValue) ? initialValue() : initialValue : undefined, ); }; export function useStateWire(upLink: StateWire): StateWire; export function useStateWire( upLink: StateWire | null | undefined, initialValue: InitializerOrValue, ): StateWire; export function useStateWire( upLink: StateWire | null | undefined, initialValue?: InitializerOrValue, ): StateWire; export function useStateWire( upLink: StateWire | null | undefined, initialValue?: InitializerOrValue, ): StateWire | StateWire { const [[wire, connect], set] = useState(() => create(upLink, initialValue)); const lastUpLinkRef = useRef(upLink); if ( !isBrowser && upLink && upLink.getValue() === undefined && wire.getValue() !== undefined ) { console.error( 'upLink value is undefined. uplink without value is not supported in server side rendering', ); } useIsomorphicLayoutEffect(() => { if (lastUpLinkRef.current !== upLink) { lastUpLinkRef.current = upLink; set(create(upLink, wire.getValue())); } }, [upLink, wire]); useEffect(() => { return connect(); }, [connect]); return wire; }