import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';
import type {
ReactContext,
StartTransitionOptions,
Usable,
Awaited,
} from 'shared/ReactTypes';
import {REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {enableAsyncActions} from 'shared/ReactFeatureFlags';
import {
enableContextProfiling,
enableLazyContextPropagation,
} from '../../shared/ReactFeatureFlags';
type BasicStateAction<S> = (S => S) | S;
type Dispatch<A> = A => void;
function resolveDispatcher() {
const dispatcher = ReactSharedInternals.H;
if (__DEV__) {
if (dispatcher === null) {
console.error(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',
);
}
}
return ((dispatcher: any): Dispatcher);
}
export function getCacheForType<T>(resourceType: () => T): T {
const dispatcher = ReactSharedInternals.A;
if (!dispatcher) {
return resourceType();
}
return dispatcher.getCacheForType(resourceType);
}
export function useContext<T>(Context: ReactContext<T>): T {
const dispatcher = resolveDispatcher();
if (__DEV__) {
if (Context.$$typeof === REACT_CONSUMER_TYPE) {
console.error(
'Calling useContext(Context.Consumer) is not supported and will cause bugs. ' +
'Did you mean to call useContext(Context) instead?',
);
}
}
return dispatcher.useContext(Context);
}
export function unstable_useContextWithBailout<T>(
context: ReactContext<T>,
select: (T => Array<mixed>) | null,
): T {
if (!(enableLazyContextPropagation && enableContextProfiling)) {
throw new Error('Not implemented.');
}
const dispatcher = resolveDispatcher();
if (__DEV__) {
if (context.$$typeof === REACT_CONSUMER_TYPE) {
console.error(
'Calling useContext(Context.Consumer) is not supported and will cause bugs. ' +
'Did you mean to call useContext(Context) instead?',
);
}
}
return dispatcher.unstable_useContextWithBailout(context, select);
}
export function useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
export function useReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: I => S,
): [S, Dispatch<A>] {
const dispatcher = resolveDispatcher();
return dispatcher.useReducer(reducer, initialArg, init);
}
export function useRef<T>(initialValue: T): {current: T} {
const dispatcher = resolveDispatcher();
return dispatcher.useRef(initialValue);
}
export function useEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, deps);
}
export function useInsertionEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useInsertionEffect(create, deps);
}
export function useLayoutEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useLayoutEffect(create, deps);
}
export function useCallback<T>(
callback: T,
deps: Array<mixed> | void | null,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useCallback(callback, deps);
}
export function useMemo<T>(
create: () => T,
deps: Array<mixed> | void | null,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useMemo(create, deps);
}
export function useImperativeHandle<T>(
ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
create: () => T,
deps: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useImperativeHandle(ref, create, deps);
}
export function useDebugValue<T>(
value: T,
formatterFn: ?(value: T) => mixed,
): void {
if (__DEV__) {
const dispatcher = resolveDispatcher();
return dispatcher.useDebugValue(value, formatterFn);
}
}
export function useTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
const dispatcher = resolveDispatcher();
return dispatcher.useTransition();
}
export function useDeferredValue<T>(value: T, initialValue?: T): T {
const dispatcher = resolveDispatcher();
return dispatcher.useDeferredValue(value, initialValue);
}
export function useId(): string {
const dispatcher = resolveDispatcher();
return dispatcher.useId();
}
export function useSyncExternalStore<T>(
subscribe: (() => void) => () => void,
getSnapshot: () => T,
getServerSnapshot?: () => T,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
}
export function useCacheRefresh(): <T>(?() => T, ?T) => void {
const dispatcher = resolveDispatcher();
return dispatcher.useCacheRefresh();
}
export function use<T>(usable: Usable<T>): T {
const dispatcher = resolveDispatcher();
return dispatcher.use(usable);
}
export function useMemoCache(size: number): Array<any> {
const dispatcher = resolveDispatcher();
return dispatcher.useMemoCache(size);
}
export function useEffectEvent<Args, F: (...Array<Args>) => mixed>(
callback: F,
): F {
const dispatcher = resolveDispatcher();
return dispatcher.useEffectEvent(callback);
}
export function useOptimistic<S, A>(
passthrough: S,
reducer: ?(S, A) => S,
): [S, (A) => void] {
const dispatcher = resolveDispatcher();
return dispatcher.useOptimistic(passthrough, reducer);
}
export function useActionState<S, P>(
action: (Awaited<S>, P) => S,
initialState: Awaited<S>,
permalink?: string,
): [Awaited<S>, (P) => void, boolean] {
if (!enableAsyncActions) {
throw new Error('Not implemented.');
} else {
const dispatcher = resolveDispatcher();
return dispatcher.useActionState(action, initialState, permalink);
}
}