添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本文源码解析react版本:17.0.3

1、Hook概述

Hook 是 React 16.8 的新增特性,它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hook的诞生,是为共享状态逻辑提供更好的原生途径。React官方文档,已经对hook进行了十分全面的介绍: https://reactjs.org/docs/hooks-intro.html

2、 React Hook源码文件

文件位置:packages/react/src/ReactHooks.js

* This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * @flow import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type { MutableSource, MutableSourceGetSnapshotFn, MutableSourceSubscribeFn, ReactContext, } from 'shared/ReactTypes'; import type {OpaqueIDType} from 'react-reconciler/src/ReactFiberHostConfig'; import ReactCurrentDispatcher from './ReactCurrentDispatcher'; type BasicStateAction<S> = (S => S) | S; type Dispatch<A> = A => void; function resolveDispatcher() { const dispatcher = ReactCurrentDispatcher.current; if (__DEV__) { if (dispatcher === null) { console.error( 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + ' one of the following reasons:\n' + '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + '2. You might be breaking the Rules of Hooks\n' + '3. You might have more than one copy of React in the same app\n' + 'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.', // Will result in a null access error if accessed outside render phase. We // intentionally don't throw our own error because this is in a hot path. // Also helps ensure this is inlined. return ((dispatcher: any): Dispatcher); export function getCacheForType<T>(resourceType: () => T): T { const dispatcher = resolveDispatcher(); // $FlowFixMe This is unstable, thus optional return dispatcher.getCacheForType(resourceType); export function useContext<T>(Context: ReactContext<T>): T { const dispatcher = resolveDispatcher(); if (__DEV__) { // TODO: add a more generic warning for invalid values. if ((Context: any)._context !== undefined) { const realContext = (Context: any)._context; // Don't deduplicate because this legitimately causes bugs // and nobody should be using this in existing code. if (realContext.Consumer === Context) { console.error( 'Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be ' + 'removed in a future major release. Did you mean to call useContext(Context) instead?', } else if (realContext.Provider === Context) { console.error( 'Calling useContext(Context.Provider) is not supported. ' + 'Did you mean to call useContext(Context) instead?', return dispatcher.useContext(Context); export function useState<S>( initialState: (() => S) | S, ): [S, Dispatch<BasicStateAction<S>>] { const dispatcher = resolveDispatcher(); return dispatcher.useState(initialState); export function useReducer<S, I, A>( reducer: (S, A) => S, initialArg: I, init?: I => S, ): [S, Dispatch<A>] { const dispatcher = resolveDispatcher(); return dispatcher.useReducer(reducer, initialArg, init); export function useRef<T>(initialValue: T): {|current: T|} { const dispatcher = resolveDispatcher(); return dispatcher.useRef(initialValue); export function useEffect( create: () => (() => void) | void, deps: Array<mixed> | void | null, ): void { const dispatcher = resolveDispatcher(); return dispatcher.useEffect(create, deps); export function useLayoutEffect( create: () => (() => void) | void, deps: Array<mixed> | void | null, ): void { const dispatcher = resolveDispatcher(); return dispatcher.useLayoutEffect(create, deps); export function useCallback<T>( callback: T, deps: Array<mixed> | void | null, ): T { const dispatcher = resolveDispatcher(); return dispatcher.useCallback(callback, deps); export function useMemo<T>( create: () => T, deps: Array<mixed> | void | null, ): T { const dispatcher = resolveDispatcher(); return dispatcher.useMemo(create, deps); export function useImperativeHandle<T>( ref: {|current: T | null|} | ((inst: T | null) => mixed) | null | void, create: () => T, deps: Array<mixed> | void | null, ): void { const dispatcher = resolveDispatcher(); return dispatcher.useImperativeHandle(ref, create, deps); export function useDebugValue<T>( value: T, formatterFn: ?(value: T) => mixed, ): void { if (__DEV__) { const dispatcher = resolveDispatcher(); return dispatcher.useDebugValue(value, formatterFn); export const emptyObject = {}; export function useTransition(): [boolean, (() => void) => void] { const dispatcher = resolveDispatcher(); return dispatcher.useTransition(); export function useDeferredValue<T>(value: T): T { const dispatcher = resolveDispatcher(); return dispatcher.useDeferredValue(value); export function useOpaqueIdentifier(): OpaqueIDType | void { const dispatcher = resolveDispatcher(); return dispatcher.useOpaqueIdentifier(); export function useMutableSource<Source, Snapshot>( source: MutableSource<Source>, getSnapshot: MutableSourceGetSnapshotFn<Source, Snapshot>, subscribe: MutableSourceSubscribeFn<Source, Snapshot>, ): Snapshot { const dispatcher = resolveDispatcher(); return dispatcher.useMutableSource(source, getSnapshot, subscribe); export function useCacheRefresh(): <T>(?() => T, ?T) => void { const dispatcher = resolveDispatcher(); // $FlowFixMe This is unstable, thus optional return dispatcher.useCacheRefresh();

从源码中看出调用dispatcher函数进行初始化和更新

3、 Hooks初始化和更新

文件目录:packages/react-reconciler/src/ReactFiberHooks.new.js

export function renderWithHooks<Props, SecondArg>(
  current: Fiber | null,
  workInProgress: Fiber,
  Component: (p: Props, arg: SecondArg) => any,
  props: Props,
  secondArg: SecondArg,
  nextRenderLanes: Lanes,
): any {
  renderExpirationTime = nextRenderExpirationTime;
  currentlyRenderingFiber = workInProgress;
      // 如果current的值为空,说明还没有hook对象被挂载
  // 而根据hook对象结构可知,current.memoizedState指向下一个current
  nextCurrentHook = current !== null ? current.memoizedState : null;
 // 用nextCurrentHook的值来区分mount和update,设置不同的dispatcher
  ReactCurrentDispatcher.current =
      nextCurrentHook === null
      // 初始化时
        ? HooksDispatcherOnMount
          // 更新时
        : HooksDispatcherOnUpdate;
// 此时已经有了新的dispatcher,在调用Component时就可以拿到新的对象
  let children = Component(props, secondArg);
  .....
  return children;

3.1 初始化与更新

请参考:useState原理解析

参考资料:React技术揭秘

本文源码解析react版本:17.0.31、Hook概述Hook 是 React 16.8 的新增特性,它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hook的诞生,是为共享状态逻辑提供更好的原生途径。React官方文档,已经对hook进行了十分全面的介绍:https://reactjs.org/docs/hooks-intro.html2、 React Hook源码文件文件位置:packages/react/src/ReactHooks.js
文章目录源码分析:react hook 最佳实践(上篇)前言2条规则为什么?源码分析useState使用方式为什么?源码分析useEffect使用方式为什么?源码分析useMemo使用方式为什么?源码分析useCallback使用方式为什么?源码分析下篇介绍 源码分析:react hook 最佳实践(上篇) 本文从 mini React —— Preact 源码的角度,分析 Rea...
hooks是function组件渲染中的一个环节。作用是将一部分组件的数据处理逻辑独立出来,以渐进式方式的加入到函数组件中。 源码地址packages/react-reconciler/src/ReactFiberHooks.js 根据源码实现简易hookDemo的代码地址:src/hookDemo目录下的CommonDemo组件 来玩局游戏吧! 废话不多说,上图:
前段时间研究了一波React的渲染流程,内部机制的源码,阅读到一半的时候React终于推出了16.8.x的版本,主要带来的更新就是Hooks的新功能。相信已经有很多的使用教程或者源码阅读文章。那么我也来一个属于自己的阅读有感的文章,做一个记录吧。 其实React文档中也有说明了Hooks的提出主要是为了解决什么问题的。 React团队认为组件之间复用状态逻辑很难。 就以前React为了将一个组...