react hooks实现原理(useState为例)

一、源代码

逻辑十分绕,建议多敲几遍。

let isMount = true; // 判断是挂载还是更新
let workInProgressHook;

// App组件对应的fiber对象
const fiber = {
    memorizedState: null,  // 当前hook的相关信息
    stateNode: App
}

function schedule() {
    // 更新前将workInProgressHook重置为fiber保存的第一个Hook
    workInProgressHook = fiber.memorizedState;

    const app = fiber.stateNode();
    isMount = false;

    return app; // 方便调试 触发事件
}

/**
 * 调用setState方法,相当于调用这个方法,从而实现state状态更新
 * @param {*} queue 
 * @param {*} action 
 */
function dispatchAction(queue, action) {
    const update = {
        action,
        next: null
    }

    // 环状链表
    if (queue.pending === null) {
        update.next = update;
    } else {
        update.next = queue.pending.next;
        queue.pending.next = update;
    }

    queue.pending = update;

    // 开始调度
    schedule();
}

// 手写hook
function useState (initalState) {
    let hook;

    // 最开始刚挂载的时候
    if (isMount) {
        hook = {
            queue: {
                pending: null
            },
            memorizedState: initalState,
            next: null
        }

        // 初始化时候 只调用一次 setState的情况
        if (!fiber.memorizedState) {
            fiber.memorizedState = hook;
        
            // 初始化的时候 有多个useState的情况
        } else {
            // 不断追加到链表后面
            workInProgressHook.next = hook;
        }

        workInProgressHook = hook;
    } 
    // 执行update操作的时候
    else {
        hook = workInProgressHook;
        workInProgressHook = workInProgressHook.next;
    }

    let baseState = hook.memorizedState;
    
    if (hook.queue.pending) {
        let firstUpdate = hook.queue.pending.next;

        do {
            const {action} = firstUpdate;
            baseState = action(baseState);
            firstUpdate = firstUpdate.next;
        } while(firstUpdate !== hook.queue.pending)

        hook.queue.pending = null;
    }

    hook.memorizedState = baseState;

    return [baseState, dispatchAction.bind(null, hook.queue)]
}


// 组件
function App() {
    const [state, setState] = useState(0);
    const [state2, setState2] = useState(1);

    console.log('workInProgressHook', workInProgressHook, state, state2)

    return {
        click () {
            setState(state => state + 1);
            setState(state => state + 1);
        },
        focus () {
            setState2(state2 => state2 + 1)
        }
    }
}

window.app = schedule();

二、参考资料

  1. React技术揭秘
  2. B站:React Hooks的理念、实现、源码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React Hooks 是 React 16.8 版本引入的一种新特性,它是为了使函数组件能够拥有状态和其他 React 特性而设计的。 React Hooks 的原理基于两个核心概念:闭包和钩子函数。 1. 闭包:在函数组件内部,可以通过闭包的方式引用外部作用域的变量。React Hooks 利用了闭包的特性,使得可以在函数组件内部存储和更新状态。 2. 钩子函数:React Hooks 提供了一系列的钩子函数,如 useStateuseEffect、useContext 等。这些钩子函数是预定义的特殊函数,可以在函数组件中使用,通过调用这些钩子函数,可以获取和操作组件的状态、副作用和上下文等。 当一个组件使用了 React Hooks,React 在底层会创建一个与该组件实例相关联的 Fiber 对象,并在组件渲染时执行组件函数。在执行组件函数时,React 跟踪每个组件函数内部所有的钩子函数调用,并将其与该组件实例相关联。 当组件函数执行时,如果遇到 useState 钩子调用,React 会查找该钩子函数对应的状态值,并将其返回给组件函数。组件通过 useState 返回的状态值可以读取和更新组件的状态。 当组件函数执行完毕后,React 会将该组件的状态和副作用存储在 Fiber 对象中,并将 Fiber 对象添加到更新队列中。之后,React 会根据更新队列中的 Fiber 对象,对组件进行批量更新,实现页面的重新渲染。 通过这种方式,React Hooks 实现了函数组件的状态管理和副作用处理,使得开发者可以更方便地编写和维护 React 组件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值