1. 实现 useEffect

本次课程我们来开始实现一下mini-react中的useEffect。我们先来是先最简单的,没有依赖的情况。

在app.js加上useEffect

jsx 复制代码
 React.useEffect(() => {
    console.log('useEffect')
  }, [])

创建函数,先存起来参数

jsx 复制代码
function useEffect(callback, deps) {
    const effctHook = {
        callback,
        deps
    }
}

调用时机

  • 应该在dom的渲染之后,也就是处理完所有的节点之后调用
  • react.js
jsx 复制代码
function commitRoot() {
    deletions.forEach(commitDeletion)
    commitWork(wipRoot.child)
    commitEffectHook()
    currentRoot = wipRoot
    wipRoot = null
    deletions = []
}
​
function commitEffectHook() {
    function run(fiber) {
        if (!fiber) {
            return
        }
        fiber?.effectHook?.callback()
        run(fiber.child)
        run(fiber.sibling)
    }
    run(wipFiber)
}
​
function useEffect(callback, deps) {
    const effectHook = {
        callback,
        deps
    }
    wipFiber.effectHook = effectHook
}
​
const React = {
    render,
    useState,
    useEffect,
    createElement,
    update
}

1.png

增加依赖项count

  • app.jsx
jsx 复制代码
import React from "./core/React.js";
​
function Foo() {
  console.log('fooo')
  const [bar, setBar] = React.useState('bar')
  function handleClick() {
    setBar('bar')
    setCount(c => c + 1)
  }
​
  const [count, setCount] = React.useState(10);
​
  React.useEffect(() => {
    console.log('useEffect')
  }, [count])
​
  return (
    <div>
      {bar}
      {count}
      <button onClick={handleClick}>click</button>
    </div>
  );
}
​
function App() {
  return (
    <div>
      <Foo />
    </div>
  );
}
​
export default App;
  • 更新核心代码react.js
jsx 复制代码
function commitEffectHook() {
    function run(fiber) {
// ...
        if(!fiber.alternate) {
            fiber.effectHook?.callback()
        }else {
            // update
            // deps 有没有发生改变
            const oldEffectHook = fiber.alternate?.effectHook
​
            // some
            const needUpdate = oldEffectHook?.deps.some((oldDep, index) => {
                return oldDep !== fiber.effectHook.deps[index]
            })
​
            needUpdate && fiber.effectHook?.callback()
​
        }
​
// ...
    }
    run(wipFiber)
}

开始实现多个

  • app.jsx
jsx 复制代码
  React.useEffect(() => {
    console.log('init')
  }, [])
​
  React.useEffect(() => {
    console.log('update', count)
  }, [count])
  • react.js
jsx 复制代码
function commitRoot() {
    deletions.forEach(commitDeletion)
    commitWork(wipRoot.child)
    commitEffectHooks()
    currentRoot = wipRoot
    wipRoot = null
    deletions = []
}
​
function commitEffectHooks() {
    function run(fiber) {
        if (!fiber) {
            return
        }
​
        if(!fiber.alternate) {
            fiber?.effectHooks?.forEach((hook) => {
                hook.callback()
            })
        }else {
            // update
            // deps 有没有发生改变
            fiber.effectHooks?.forEach((newHook, index)=> {
                if(newHook.deps.length> 0 ) {
                    const oldEffectHook = fiber.alternate?.effectHooks[index]
​
                    // some
                    const needUpdate = oldEffectHook?.deps.some((oldDep, i) => {
                        return oldDep !== newHook.deps[i]
                    })
​
                    needUpdate && newHook.callback()
                }
            })
        }
​
        run(fiber.child)
        run(fiber.sibling)
    }
    run(wipFiber)
}
​
function updateFunctionComponent(fiber) {
    effectHooks = []
    stateHooks = []
    stateHookIndex = 0
    wipFiber = fiber
    const children = [fiber.type(fiber.props)]
    reconcileChildren(fiber, children)
}
​
let effectHooks
function useEffect(callback, deps) {
    const effectHook = {
        callback,
        deps
    }
    effectHooks.push(effectHook)
    wipFiber.effectHooks = effectHooks
}
相关推荐
JNU freshman12 分钟前
Element Plus组件
前端·vue.js·vue3
一只专注api接口开发的技术猿19 分钟前
容器化与调度:使用 Docker 与 K8s 管理分布式淘宝商品数据采集任务
开发语言·前端·数据库
我有一棵树24 分钟前
性能优化之前端与服务端中的 Gzip 压缩全解析
前端
魔术师卡颂28 分钟前
不就写提示词?提示词工程为啥是工程?
前端·人工智能·后端
訾博ZiBo1 小时前
【Vibe Coding】001-前端界面常用布局
前端
IT_陈寒1 小时前
《Redis性能翻倍的7个冷门技巧,90%开发者都不知道!》
前端·人工智能·后端
歪歪1001 小时前
React Native开发Android&IOS流程完整指南
android·开发语言·前端·react native·ios·前端框架
知识分享小能手1 小时前
uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
前端·javascript·学习·微信小程序·小程序·前端框架·uni-app
ZYMFZ1 小时前
python面向对象
前端·数据库·python
长空任鸟飞_阿康1 小时前
在 Vue 3.5 中优雅地集成 wangEditor,并定制“AI 工具”下拉菜单(总结/润色/翻译)
前端·vue.js·人工智能