总结
总结
为什么要引入 hook
在组件之间复用状态逻辑很难
复杂组件变得难以理解
难以理解的 class
1 状态管理: 在函数组件中引入 useState,无需类组件也能管理状态。
2 副作用处理:通过 useEffect 统一处理生命周期逻辑,避免类组件中复杂的生命周期方法。
3 解决逻辑复用难的问题。
4 放弃面向对象编程,拥抱函数式编程。
目前常见的 hooks
useState: setState
useReducer: setState
useRef: ref
useImperativeMethods: ref
useContext: context
useCallback: 可以对setState的优化
useMemo: useCallback的变形
useLayoutEffect: 类似componentDidMount/Update, componentWillUnmount
useEffect: 类似于setState(state, cb)中的cb,总是在整个更新周期的最后才执行
类实例成员变量如何映射到 hooks
hooks 中如何获取历史 props 和 state
调用 State Hook 的更新函数并传入当前的 state 时,React 将跳过子组件的渲染及 effect 的执行。(React 使用 Object.is 比较算法 来比较 state。)
用副作用来同步 count 的值
如何强制更新一个 hook 组件
useEffect 对于函数依赖,尝试将该函数放置在 effect 内,或者使用 useCallback 包裹;useEffect/useCallback/useMemo,对于 state 或者其他属性的依赖,根据 eslint 的提示填入 deps;如果不直接使用 state,只是想修改 state,用 setState 的函数入参方式(setState(c => c + 1))代替;如果修改 state 的过程依赖了其他属性,尝试将 state 和属性聚合,改写成 useReducer 的形式。当这些方法都不奏效,使用 ref,但是依然要谨慎操作。
赋予函数组件类组件的能力
useReducer 跟 useState 差不多
useEffect 和 useLayoutEffect
memo 提供了类似 class ComponentShouldUpdate 的功能
ref 不能挂载 function Component 上面 一般来说我们都是用在 class 实例上
*/ const ReactCurrentOwner = { /**
@internal
@type {ReactComponent} */ current: (null: null | Fiber), currentDispatcher: (null: null | Dispatcher), };
export default ReactCurrentOwner;
我们在 ReactHooks.js 里面可以看到
再看一下 resloveDispatcher 它来自 ReactCurrentOwner
在 ReactFiberHooks 中 我们可以看到
而它们的实现又是从 reactBeginWork.js 先 prepareToReadContext 接着 prepareToUseHooks 中间执行 Component 最后执行 finishHooks
从打的断点可以知道 firstWorkInProgressHook = workInProgressHook
redux 作者 Dan 加入到 React 推行了 Hook
我们每个 fiber 对应每个组件,hook 代表更细粒度的 fiber,
Hooks Capture props 属性
只要将赋值与取值的对象变成 useRef,而不是 useState,就可以躲过 capture value 特性,在 3 秒后得到最新的值
替代 shouldComponentUpdate 得方案
或者
怎么替代 componentDidUpdate
由于 useEffect 每次 Render 都会执行,因此需要模拟一个 useUpdate 函数:
怎么替代 forceUpdate
React 官方文档提供了一种方案:
每次执行 dispatch 时,只要 state 变化就会触发组件更新
state 拆分过多
只是更新的时候,不再会自动 merge,而需要使用 ...state 语法:
获取上一个 props
性能注意事项
useState 函数的参数虽然是初始值,但由于整个函数都是 render, 因此每次初始化都会被调用,如果初始值计算非常消耗实践,建议使用函数传入,这样只会执行一次
写 react hooks 的一些思考, “有状态的组件没有渲染,有渲染的组件没有状态”:
利用 useState 创建 Redux
hook
hook 可以看做是函数组件和与其对应的 fiber 节点进行沟通和的操作的纽带。在 react 中处于不同阶段的 fiber 节点会被赋予不同的处理函数执行 hook:
初始化阶段 -----> HookDispatcherOnMount
更新阶段 -----> HookDispatcherOnUpdate
如何确定 fiber 对应的 hook 上下文?
在我们执行 hook 相关的逻辑时,讲当前 fiber 节点信息保存在一个全局变量中。
hook 是如何存在的?保存在什么地方?
在 react 中,hook 是保存在 fiber 节点上的,每个 fiber 节点都有一个 memoizedState 属性,用来保存当前 fiber 节点对应的 hook 上下文。
fiber 节点中保存着非常多的属性,有作为构造 fiber 链表,用于保存位置信息的属性,有作为保存更新队列的属性等等。
而对于函数组件类型的 fiber 节点,memoizedState 属性保存 hooks 信息。hook 在初始化时,会创建一个对象,保存此 hook 所产生的计算值,更新队列,hook 链表。
多个 hook 如何处理?
在某个函数组件中存在多个 hook,此时每个 hook 的信息该如何保存呢?这就是上文中 hook 对象中 next 属性的作用,它是一个链表指针。在 hook 对象中,next 属性指向下一个 hook。

换句话说,如果在一个函数组件中存在多个 hook,那么在该 fiber 节点的 memoizedState 属性中保存着一个 hook 链表,每个 hook 对象中的 next 属性指向下一个 hook。
函数组件对应 fiber 用 memoizedState 保存 hook 信息,每一个 hook 执行都会产生一个 hook 对象,hook 对象中,保存着当前 hook 的信息,不同 hook 保存的形式不同。每一个 hook 通过 next 链表建立起关系。
最后更新于
这有帮助吗?