react hook 源码完全解读

本文深入浅出地探讨React Hooks的源码实现,特别是useState、useReducer和useEffect。通过源码分析,解答了如何区分和管理Hooks、如何在每次渲染时返回最新值以及Hooks链表的存放位置等问题。文章详细解释了React如何通过单链表管理Hooks,并在组件渲染过程中维护更新链表以确保状态的正确性。
摘要由CSDN通过智能技术生成

前言

从React Hooks发布以来,整个社区都以积极的态度去拥抱它、学习它。期间也涌现了很多关于React Hooks 源码解析的文章。本文就以笔者自己的角度来写一篇属于自己的文章吧。希望可以深入浅出、图文并茂的帮助大家对React Hooks的实现原理进行学习与理解。本文将以文字、代码、图画的形式来呈现内容。主要对常用Hooks中的 useState、useReducer、useEffect 进行学习,尽可能的揭开Hooks的面纱。

使用Hooks时的疑惑

Hooks的面世让我们的Function Component逐步拥有了对标Class Component的特性,比如私有状态,生命周期函数等。useState与useReducer这两个Hooks让我们可以在 Function Component里使用到私有状态。而useState其实就是阉割版的useReducer,这也是我那它们两个放在一起讲的原因。应用一下官方的例子:

function PersionInfo ({
    initialAge,initialName}) {
   
  const [age, setAge] = useState(initialAge);
  const [name, setName] = useState(initialName);
  return (
    <>
      Age: {
   age}, Name: {
   name}
      <button onClick={
   () => setAge(age + 1)}>Growing up</button>
    </>
  );
}

通过 useState 我们可以初始化一个私有状态,它会返回这个状态的最新值和一个用来更新状态的方法。而useReducer则是针对更复杂的状态管理场景:

const initialState = {
   age: 0, name: 'Dan'};

function reducer(state, action) {
   
  switch (action.type) {
   
    case 'increment':
      return {
   ...state, age: state.age + action.age};
    case 'decrement':
      return {
   ...state, age: state.age - action.age};
    default:
      throw new Error();
  }
}
function PersionInfo() {
   
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Age: {
   state.age}, Name: {
   state.name}      <button onClick={
   () => dispatch({
   type: 'decrement', age: 1})}>-</button>
      <button onClick={
   () => dispatch({
   type: 'increment', age: 1})}>+</button>
    </>
  );
}

同样也是返回当前最新的状态,并返回一个用来更新数据的方法。在使用这两个方法的时候也许我们会想过这样的问题:

  const [age, setAge] = useState(initialAge);
  const [name, setName] = useState(initialName);

React内部是怎么区分这两个状态的呢? Function Component 不像 Class Component那样可以将私有状态挂载到类实例中并通过对应的key来指向对应的状态,而且每次的页面的刷新或者说组件的重新渲染都会使得 Function 重新执行一遍。所以React中必定有一种机制来区分这些Hooks。

 const [age, setAge] = useState(initialAge);
 // 或
 const [state, dispatch] = useReducer(reducer, initialState);

另一个问题就是React是如何在每次重新渲染之后都能返回最新的状态? Class Component因为自身的特点可以将私有状态持久化的挂载到类实例上,每时每刻保存的都是最新的值。而 Function Component 由于本质就是一个函数,并且每次渲染都会重新执行。所以React必定拥有某种机制去记住每一次的更新操作,并最终得出最新的值返回。当然我们还会有其他的一些问题,比如这些状态究竟存放在哪?为什么只能在函数顶层使用Hooks而不能在条件语句等里面使用Hooks?

答案尽在源码之中

我们先来了解useState以及useReducer的源码实现,并从中解答我们在使用Hooks时的种种疑惑。首先我们从源头开始:

import React, {
    useState } from 'react';

在项目中我们通常会以这种方式来引入useState方法,被我们引入的这个useState方法是什么样子的呢?其实这个方法就在源码 packages/react/src/ReactHook.js 中。

// packages/react/src/ReactHook.js
import ReactCurrentDispatcher from './ReactCurrentDispatcher';

function resolveDispatcher() {
   
  const dispatcher = ReactCurrentDispatcher.current;
  // ... 
  return dispatcher;
}

// 我们代码中引入的useState方法
export function useState(initialState) {
   
  const dispatcher = resolveDispatcher()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值