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
}
相关推荐
乾元几秒前
绕过艺术:使用 GANs 对抗 Web 防火墙(WAF)
前端·网络·人工智能·深度学习·安全·架构
HWL56792 分钟前
一个CSS属性will-change: transform
前端·css
Y淑滢潇潇2 分钟前
WEB 作业 即时内容发布前端交互案例
前端·javascript·交互
比特森林探险记5 分钟前
后端开发者快速入门react
开发语言·前端·javascript
李松桃10 分钟前
python第三次作业
java·前端·python
熊猫钓鱼>_>28 分钟前
从零到一:打造“抗造” Electron 录屏神器的故事
前端·javascript·ffmpeg·electron·node·录屏·record
晚霞的不甘1 小时前
Flutter for OpenHarmony《智慧字典》 App 主页深度优化解析:从视觉动效到交互体验的全面升级
前端·flutter·microsoft·前端框架·交互
我是伪码农1 小时前
Vue 1.28
前端·javascript·vue.js
鹓于1 小时前
Excel一键生成炫彩二维码
开发语言·前端·javascript
siwangdexie_new1 小时前
html格式字符串转word文档,前端插件( html-docx-js )遇到兼容问题的解决过程
前端·javascript·html