React 钩子
一、作用
二、获取类型缓存
备注
ReactSharedInternals()由 ReactSharedInternals 实现
export function getCacheForType<T>(resourceType: () => T): T {
const dispatcher = ReactSharedInternals.A;
if (!dispatcher) {
// If there is no dispatcher, then we treat this as not being cached.
// 如果没有调度器,那么我们将其视为未缓存。
return resourceType();
}
return dispatcher.getCacheForType(resourceType);
}
三、useContext()
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);
}
四、useState()
export function useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
五、useReducer()
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);
}
六、useRef()
export function useRef<T>(initialValue: T): { current: T } {
const dispatcher = resolveDispatcher();
return dispatcher.useRef(initialValue);
}
七、useEffect()
export function useEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
if (__DEV__) {
if (create == null) {
console.warn(
'React Hook useEffect requires an effect callback. Did you forget to pass a callback to the hook?',
);
}
}
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, deps);
}
八、useInsertionEffect()
export function useInsertionEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
if (__DEV__) {
if (create == null) {
console.warn(
'React Hook useInsertionEffect requires an effect callback. Did you forget to pass a callback to the hook?',
);
}
}
const dispatcher = resolveDispatcher();
return dispatcher.useInsertionEffect(create, deps);
}
九、useLayoutEffect()
export function useLayoutEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
if (__DEV__) {
if (create == null) {
console.warn(
'React Hook useLayoutEffect requires an effect callback. Did you forget to pass a callback to the hook?',
);
}
}
const dispatcher = resolveDispatcher();
return dispatcher.useLayoutEffect(create, deps);
}
十、useCallback()
export function useCallback<T>(
callback: T,
deps: Array<mixed> | void | null,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useCallback(callback, deps);
}
十一、useMemo()
export function useMemo<T>(
create: () => T,
deps: Array<mixed> | void | null,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useMemo(create, deps);
}
十二、useImperativeHandle()
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);
}
十三、useDebugValue()
export function useDebugValue<T>(
value: T,
formatterFn: ?((value: T) => mixed),
): void {
if (__DEV__) {
const dispatcher = resolveDispatcher();
return dispatcher.useDebugValue(value, formatterFn);
}
}
十四、useTransition()
export function useTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
const dispatcher = resolveDispatcher();
return dispatcher.useTransition();
}
十五、useDeferredValue()
export function useDeferredValue<T>(value: T, initialValue?: T): T {
const dispatcher = resolveDispatcher();
return dispatcher.useDeferredValue(value, initialValue);
}
十六、useId()
export function useId(): string {
const dispatcher = resolveDispatcher();
return dispatcher.useId();
}
十七、useSyncExternalStore()
export function useSyncExternalStore<T>(
subscribe: (() => void) => () => void,
getSnapshot: () => T,
getServerSnapshot?: () => T,
): T {
const dispatcher = resolveDispatcher();
return dispatcher.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
}
十八、useCacheRefresh()
export function useCacheRefresh(): <T>(?() => T, ?T) => void {
const dispatcher = resolveDispatcher();
return dispatcher.useCacheRefresh();
}
十九、use()
export function use<T>(usable: Usable<T>): T {
const dispatcher = resolveDispatcher();
return dispatcher.use(usable);
}
二十、useMemoCache)
export function useMemoCache(size: number): Array<mixed> {
const dispatcher = resolveDispatcher();
return dispatcher.useMemoCache(size);
}
廿一、useEffectEvent()
// export function useEffectEvent<Args, F: (...Array<Args>) => mixed>(
export function useEffectEvent<Args, F extends (...arr: Array<Args>) => mixed>(
callback: F,
): F {
const dispatcher = resolveDispatcher();
return dispatcher.useEffectEvent(callback);
}
廿二、useOptimistic()
export function useOptimistic<S, A>(
passthrough: S,
reducer: ?((S, A) => S),
): [S, (A) => void] {
const dispatcher = resolveDispatcher();
return dispatcher.useOptimistic(passthrough, reducer);
}
廿三、useActionState()
export function useActionState<S, P>(
// action: (Awaited<S>, P) => S,
action: (awaited: Awaited<S>, p: P) => S,
initialState: Awaited<S>,
permalink?: string,
): [Awaited<S>, (P) => void, boolean] {
const dispatcher = resolveDispatcher();
return dispatcher.useActionState(action, initialState, permalink);
}
廿四、工具
1. 解析调度器
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.',
);
}
}
// Will result in a null access error if accessed outside render phase. We
// intentionally don't throw our own error because this is in a hot path.
// Also helps ensure this is inlined.
//
// 如果在渲染阶段之外访问,将导致 null 访问错误。我们故意不抛出自己的错误,因为这是热路径的
// 一部分。同时有助于确保此代码被内联。
return dispatcher as any as Dispatcher;
}