React Structure
React 源代码基础结构理解:
- React Core: all top-level APIs;React core only includes the APIs necessary to define components
- React Render: ReactDOMRender / ReactNativeRender / RaxRender / WeexRender …
- React Reconcilers: share a lot of logic among different renders, especially the declarative rendering algorithms, reconciliation algorithm.
- Stack Reconciler (React 15 based)
- Fiber Reconciler (React 16 based)
:::info 分层架构,IoC 的实践;经济体的 LowcodeEngine 也借鉴了不少类似的分层模式; :::
Hooks
export function useEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null,
): void {
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, deps);
}
- Fiber Tree
- Fiber:renderWithHooks 函数的实现背景
- Dispatcher & Resolver
ReactFiberHooks.new.js
- ReactCurrentDispatcher.current 👈 为了兼容渲染层 RenderDriver 而实现的 .current 指向 ReactDOM or ReactNative or Remax Driver
- Mount Hook on Fiber
function mountWorkInProgressHook(): Hook {
const hook: Hook = {
memoizedState: null,
baseState: null,
baseQueue: null,
queue: null,
next: null,
};
if (workInProgressHook === null) {
// This is the first hook in the list
currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
} else {
// Append to the end of the list
workInProgressHook = workInProgressHook.next = hook;
}
return workInProgressHook;
}
- useState() :
- 初始化:数据、调用队列和 Reducer
- 更新:dispatchAction => Fiber 节点上的 queue 对象,链式处理 state
- useEffect():
- 初始化:Fiber 节点的 updateQueue,并使用 .next 属性做关联实现调用链
一些小技巧
- React 源代码组织: pacakges/
share
公共类型、API、方法的目录; __DEV__
区分编译时和运行时;ReactFuatureFlags &
|=
Operator 的奇妙用法;用 bitwise 运算去巧妙解决 flags 的问题;currentlyRenderingFiber.effectTag |= fiberEffectTag;
invariant()
function andconsole.error
function;Runtime v.s. Compile Time; ```javascript /**- Use invariant() to assert state which your program assumes to be true. *
- Provide sprintf-style format (only %s is supported) and arguments
- to provide information about what broke and what you were
- expecting. *
- The invariant message will be stripped in production, but the invariant
- will remain to ensure logic does not differ in production. */
export default function invariant(condition, format, a, b, c, d, e, f) { throw new Error( ‘Internal React error: invariant() is meant to be replaced at compile ‘ + ‘time. There is no runtime version.’, ); }
- 经典的: `__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED` 猜测一下为啥要透露这些变量呢?
```javascript
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
const ReactSharedInternals = {
ReactCurrentDispatcher,
ReactCurrentBatchConfig,
ReactCurrentOwner,
IsSomeRendererActing,
// Used by renderers to avoid bundling object-assign twice in UMD bundles:
assign,
};
感受
- React 级别的项目,洁癖也没有「那么好」😄
- Comment / DevInfo 至关重要
- flow 🗑
- comment system 各种自我怀疑
使用 Hooks 注意
- 防止在条件、循环、return 语句中使用 Hooks
- 没有 re-render 的需求的渲染函数,尽量少用 useState,相反,使用 useRef 减少重新渲染次数
- useEffect 的依赖和销毁回调函数需要引起重视
- 涉及多次 setState 的 Hook 函数调用的时候,优先选择函数而非具体值
参考
- 官方指南:Codebase Overview
- ReactHooks 源码分析