gaowei1012 / blog

this is blog
2 stars 0 forks source link

react useState #77

Open gaowei1012 opened 3 years ago

gaowei1012 commented 3 years ago

useState 基本使用

const [count, setCount] = useState(0)

const handle_count = () => {
    setCount(count+1)
}

// render view

return (
  <div>{count}</div>
)
gaowei1012 commented 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]
}
gaowei1012 commented 3 years ago

看看源码里面是怎么实现的

// 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)
}
gaowei1012 commented 3 years ago

最终找到了,来源于 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

gaowei1012 commented 3 years ago

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的列队