path:packages/react/src/ReactHooks.js
目前 React 内置了 10 种 Hook:
- useState
- useReducer
- useContext
- useRef
- useEffect
- useLayoutEffect
- useCallback
- useMemo
- useImperativeHandle
- useDebugValue
useContext
export function useContext<T>(
Context: ReactContext,
unstable_observedBits: number | boolean | void,
) {
const dispatcher = resolveDispatcher();
if (__DEV__) {
// do something
}
return dispatcher.useContext(Context, unstable_observedBits);
}
复制代码
useState
export function useState<S>(initialState: (() => S) | S) {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
复制代码
useReducer
export function useReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: I => S,
) {
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,
inputs: Array<mixed> | void | null,
) {
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, inputs);
}
复制代码
useLayoutEffect
export function useLayoutEffect(
create: () => (() => void) | void,
inputs: Array<mixed> | void | null,
) {
const dispatcher = resolveDispatcher();
return dispatcher.useLayoutEffect(create, inputs);
}
复制代码
useCallback
export function useCallback(
callback: () => mixed,
inputs: Array<mixed> | void | null,
) {
const dispatcher = resolveDispatcher();
return dispatcher.useCallback(callback, inputs);
}
复制代码
useMemo
export function useMemo(
create: () => mixed,
inputs: Array<mixed> | void | null,
) {
const dispatcher = resolveDispatcher();
return dispatcher.useMemo(create, inputs);
}
复制代码
useImperativeHandle
export function useImperativeHandle<T>(
ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
create: () => T,
inputs: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useImperativeHandle(ref, create, inputs);
}
复制代码
useDebugValue
export function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
if (__DEV__) {
const dispatcher = resolveDispatcher();
return dispatcher.useDebugValue(value, formatterFn);
}
}
复制代码
不管哪一个 Hook,第一步都需要通过 resolveDispatcher
方法返回一个 dispatcher
对象。
resolveDispatcher
function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
invariant(
dispatcher !== null,
'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://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);
return dispatcher;
}
复制代码
resolveDispatcher
方法只是简单地获取了 ReactCurrentDispatcher
的 current
属性。当这个属性值为空时报错,否则返回这个对象。
ReactCurrentDispatcher
import ReactCurrentDispatcher from './ReactCurrentDispatcher';
复制代码
ReactCurrentDispatcher 文件
path:packages/react/src/ReactCurrentDispatcher.js
import type {Dispatcher} from 'react-reconciler/src/ReactFiberHooks';
/**
* 跟踪当前 dispatcher。
*/
const ReactCurrentDispatcher = {
/**
* @internal
* @type {ReactComponent}
*/
current: (null: null | Dispatcher),
};
export default ReactCurrentDispatcher;
复制代码
ReactCurrentDispatcher
对象的 current
属性是一个 Dispatcher
类型的对象。
Dispatcher
类型定义从 ReactFiberHooks.js
中导出,下一节,我们看看 ReactFiberHooks.js
是什么样子。