Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react useState #77

Open
gaowei1012 opened this issue Apr 14, 2021 · 4 comments
Open

react useState #77

gaowei1012 opened this issue Apr 14, 2021 · 4 comments

Comments

@gaowei1012
Copy link
Owner

gaowei1012 commented Apr 14, 2021

useState 基本使用

const [count, setCount] = useState(0)

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

// render view

return (
  <div>{count}</div>
)
@gaowei1012
Copy link
Owner Author

gaowei1012 commented Apr 14, 2021

实现基础版的 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
Copy link
Owner Author

gaowei1012 commented Apr 14, 2021

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

// 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
Copy link
Owner Author

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant