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
}
相关推荐
倔强青铜三16 分钟前
苦练Python第2天:安装 Python 与设置环境
前端·后端·python
我是若尘29 分钟前
Webpack 入门到实战 - 复习强化版
前端
晓131332 分钟前
JavaScript基础篇——第五章 对象(最终篇)
开发语言·前端·javascript
倔强青铜三34 分钟前
苦练Python第1天:为何要在2025年学习Python
前端·后端·python
满分观察网友z43 分钟前
uniapp使用video实现沉浸式在线课程学习平台
前端
当牛作馬1 小时前
React——ant-design组件库使用问题记录
前端·react.js·前端框架
0wioiw02 小时前
Flutter基础(前端教程⑨-图片)
前端·flutter
一只一只妖2 小时前
uniapp小程序无感刷新token
前端·小程序·uni-app
绅士玖2 小时前
📝 深入浅出 JavaScript 拷贝:从浅拷贝到深拷贝 🚀
前端