Open gaowei1012 opened 3 years ago
实现基础版的 useState
let memoizedState = [] // 存放hook的值数组
let cursor = 0 // 当前 memoizedState 的索引
function useState(initialVal) {
memoizedState[cursor] = memoizedState[cursor] || initialVal
const currentCursor = cursor
function steState(newState) {
memoizedState[currentCursor] = newState
cursor=0
// 渲染DOM节点
render(<App/>, document.getElementById('root'))
}
// 把当前的 state,并把 cursor 加1
return [memoizedState[cursor++], setState]
}
看看源码里面是怎么实现的
// package/react/src/reactHooks.js
export function useState<S>(initialState: (() => S) | S) {
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
// dispatcher 来自于
// package/react/src/reactHooks.js
function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
return dispatcher
}
而 dispatcher
来自与
// package/react-reconciler/src/ReactCurrentDispatcher.js
const ReactCurrentDispatcher = {
current: (null | Dispatcher)
}
最终找到了,来源于 package/react-reconciler/src/ReactFiberHook.js
export type Hook = {
memoizedState: any, // 指向当前渲染节点 Fiber, 上一次完整更新之后的最终状态值
baseState: any, // 初始化 initialState, 已经每次 dispatch 之后 newState
baseUpdate: Update<any, any> | null, // 当前需要更新的 Update ,每次更新完之后,会赋值上一个 update,方便 react 在渲染错误的边缘,数据回溯
queue: UpdateQueue<any, any> | null, // 缓存的更新队列,存储多次更新行为
next: Hook | null, // link 到下一个 hooks,通过 next 串联每一 hooks
}
通过上面我们可以发现React的Hook是一个单向链表,Hook.next指向下一个Hook
Update && UpdateQueue
type Update<S, A> = {
expirationTime: ExpirationTime, // 当前更新的过期时间
suspenseConfig: null | SuspenseConfig,
action: A,
eagerReducer: ((S, A) => S) | null,
eagerState: S | null,
next: Update<S, A> | null, // link 下一个 Update
priority?: ReactPriorityLevel, // 优先级
};
type UpdateQueue<S, A> = {
last: Update<S, A> | null,
dispatch: (A => mixed) | null,
lastRenderedReducer: ((S, A) => S) | null,
lastRenderedState: S | null,
};
Update 称作一个更新,在调度一次 React 更新时会用到,UpdateQueue是Update的列队
useState
基本使用