06 react hooks source code analysis

Why do I need a hook

React document It also explains what problems Hooks proposed to solve:

Reusing state logic between components is difficult.

In the past, in order to separate the logic of a component from reuse and not mix the rendering code into one class, React recommended using high-order components to separate the state logic and transfer it to the high-order components with state logic through different style components to enhance the function of style components, so as to achieve the function of reuse logic. mixin will be used to implement it in the early stage.

Disadvantages: by increasing the nesting level, the code will be more difficult to understand.

Complex components become difficult to understand

When using the class component, we have to add some operations in the life cycle function, such as calling some functions or initiating requests. When destroying the component, we may need to remove some events to prevent memory overflow. At this time, we need to call the same functions in componentDidMount and componentDidUpdate to obtain data, and remove events in componentWillUnmount; Because of the strong coupling with components, it is also difficult to extract them by means of high-order components. Hook divides the associated parts of components into smaller functions, and each function has a more single function.

Incomprehensible class

Hook is a class component that exists as a pure function; In the past, when we used pure functional components, there was a standard, that is, this component does not have its own life cycle and its own independent state. Simply return a component. Or assemble components according to the incoming props. However, with the release of hook, the React team wants to write components in a more functional programming way, so that the original stored function components can use some features of class components.

hook call entry

In the hook source code, the hook exists in the Dispatcher, which is an object. The functions called by different hooks are different; In the renderWithHooks function, the global variable ReactCurrentDispatcher.current will be assigned to HooksDispatcherOnMountInDEV or HooksDispatcherOnUpdateInDEV according to mount or update:

export function renderWithHooks<Props, SecondArg>(
  current: Fiber | null,
  workInProgress: Fiber,
  Component: (p: Props, arg: SecondArg) => any,
  props: Props,
  secondArg: SecondArg,
  nextRenderLanes: Lanes,
): any {
  renderLanes = nextRenderLanes;
  currentlyRenderingFiber = workInProgress;

  workInProgress.memoizedState = null;
  workInProgress.updateQueue = null;
  workInProgress.lanes = NoLanes;

  ReactCurrentDispatcher.current =
      current === null || current.memoizedState === null
        ? HooksDispatcherOnMount
        : HooksDispatcherOnUpdate;
}

const HooksDispatcherOnMount: Dispatcher = {
  readContext,

  useCallback: mountCallback,
  useContext: readContext,
  useEffect: mountEffect,
  useImperativeHandle: mountImperativeHandle,
  useLayoutEffect: mountLayoutEffect,
  useInsertionEffect: mountInsertionEffect,
  useMemo: mountMemo,
  useReducer: mountReducer,
  useRef: mountRef,
  useState: mountState,
  ...
}
  
const HooksDispatcherOnUpdate: Dispatcher = {
  readContext,

  useCallback: updateCallback,
  useContext: readContext,
  useEffect: updateEffect,
  useImperativeHandle: updateImperativeHandle,
  useInsertionEffect: updateInsertionEffect,
  useLayoutEffect: updateLayoutEffect,
  useMemo: updateMemo,
  useReducer: updateReducer,
  useRef: updateRef,
  useState: updateState,
  ...
};

Keywords: Front-end React

Added by windwaker on Tue, 23 Nov 2021 03:04:16 +0200