手写实现useState useEffect useReducer

一. useState 钩子函数的实现原理

// import { useState } from 'react'
import ReactDOM from 'react-dom'
let state = []
let setters = []
let stateIndex = 0function createSetter (index) {return function (newState) {state[index] = newStaterender()}
}function useState (initialState) {state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialStatesetters.push(createSetter(stateIndex))let value = state[stateIndex]let setter = setters[stateIndex]stateIndex ++return [value, setter]
}function render () {stateIndex = 0ReactDOM.render(<App/>,document.getElementById('root'))
}export default function App () {const [count, setCount] = useState(0)const [name, setName] = useState('张三')return <div><span>{count}</span><button onClick={() => setCount(count + 1)}> + 1</button><span>{name}</span><button onClick={() => setName('李四')}> 李四</button></div>
}

二. useEffect 钩子函数的实现原理

// import { useState } from 'react'
import ReactDOM from 'react-dom'
let state = []
let setters = []
let stateIndex = 0function createSetter (index) {return function (newState) {state[index] = newStaterender()}
}function useState (initialState) {state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialStatesetters.push(createSetter(stateIndex))let value = state[stateIndex]let setter = setters[stateIndex]stateIndex ++return [value, setter]
}function render () {stateIndex = 0effectIndex = 0ReactDOM.render(<App/>,document.getElementById('root'))
}// 上一次的依赖值
let prevDepsAry = []
let effectIndex = 0/*** useEffect* @param {function} callback 回调函数* @param {Array} depsAry 依赖数组* @returns {function} 清理函数*/
function useEffect (callback, depsAry) {if (Object.prototype.toString.call(callback) !== '[object Function]') throw new Error('useEffect 第一个参数必须是一个函数')if (typeof depsAry === 'undefined') {// 没有传递callback()} else {// 判断 depsAry 是不是数组if (Object.prototype.toString.call(depsAry) !== '[object Array]') throw new Error('useEffect 第二个参数必须是一个数组')// 获取上一次的状态值let prevDeps = prevDepsAry[effectIndex]// 将当前的依赖值和上一次的依赖值作对比,如果有变化,调用 callbacklet hasChanged = prevDeps ? !depsAry.every((dep, index) => dep === prevDeps[index]) : true// 判断值是否有变化if (hasChanged) {callback()}// 同步依赖值prevDepsAry[effectIndex++] = depsAry}
}export default function App () {const [count, setCount] = useState(0)const [name, setName] = useState('张三')useEffect(() => {console.log('Hello')}, [count])useEffect(() => {console.log('World')}, [name])// 测试不传监听数据的情况useEffect(() => {console.log('xxx')}, [])return <div><span>{count}</span><button onClick={() => setCount(count + 1)}> + 1</button><span>{name}</span><button onClick={() => setName('李四')}> 李四</button></div>
}

三.useReducer 钩子函数的实现原理

// import { useState } from 'react'
// import { useReducer } from 'react'
import ReactDOM from 'react-dom'
let state = []
let setters = []
let stateIndex = 0function createSetter (index) {return function (newState) {state[index] = newStaterender()}
}function useState (initialState) {state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialStatesetters.push(createSetter(stateIndex))let value = state[stateIndex]let setter = setters[stateIndex]stateIndex ++return [value, setter]
}function render () {stateIndex = 0effectIndex = 0ReactDOM.render(<App/>,document.getElementById('root'))
}// 上一次的依赖值
let prevDepsAry = []
let effectIndex = 0/*** useEffect* @param {function} callback 回调函数* @param {Array} depsAry 依赖数组* @returns {function} 清理函数*/
function useEffect (callback, depsAry) {if (Object.prototype.toString.call(callback) !== '[object Function]') throw new Error('useEffect 第一个参数必须是一个函数')if (typeof depsAry === 'undefined') {// 没有传递callback()} else {// 判断 depsAry 是不是数组if (Object.prototype.toString.call(depsAry) !== '[object Array]') throw new Error('useEffect 第二个参数必须是一个数组')// 获取上一次的状态值let prevDeps = prevDepsAry[effectIndex]// 将当前的依赖值和上一次的依赖值作对比,如果有变化,调用 callbacklet hasChanged = prevDeps ? !depsAry.every((dep, index) => dep === prevDeps[index]) : true// 判断值是否有变化if (hasChanged) {callback()}// 同步依赖值prevDepsAry[effectIndex++] = depsAry}
}function useReducer (reducer, initialState) {const [state, setState] = useState(initialState)function dispatch (action) {const newState = reducer(state, action)setState(newState)}return [state, dispatch]
}export default function App () {function reducer(state, action) {switch (action.type) {case 'increment':return state + 1case 'decrement':return state - 1default:return state}}const [cnt, dispatch] = useReducer(reducer, 0)return <div><div><button onClick={() => dispatch({type: 'increment'})}> + 1</button><span>{cnt}</span><button onClick={() => dispatch({type: 'decrement'})}> - 1</button></div></div>
}

手写Hooks核心原理相关推荐

  1. babel原理_手写webpack核心原理,再也不怕面试官问我webpack原理

    手写webpack核心原理 一.核心打包原理 1.1 打包的主要流程如下 1.2 具体细节 二.基本准备工作 三.获取模块内容 四.分析模块 五.收集依赖 六.ES6转成ES5(AST) 七.递归获取 ...

  2. 手写Vuex核心原理,再也不怕面试官问我Vuex原理

    手写Vuex核心原理 文章目录 手写Vuex核心原理 一.核心原理 二.基本准备工作 三.剖析Vuex本质 四.分析Vue.use 五.完善install方法 六.实现Vuex的state 七.实现g ...

  3. 手写Redux核心原理

    手写Redux核心原理 一.createStore核心逻辑实现 createStore的三个参数 reducer:根据actions类型对store中数据状态进行更改,返回一个新的状态 preload ...

  4. 定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理

    整体流程的介绍 整体流程的介绍 1. 定义整体结构 2. 实现Promise构造函数 3. 实现then方法 3.实现catch方法 4. 实现Promise.resolve 5.实现Promise. ...

  5. 05. 手写Spring核心框架

    目录 05 手写Spring核心框架 Pt1 手写IoC/DI Pt1.1 流程设计 Pt1.2 基础配置 application.properties pom.xml web.xml Pt1.3 注 ...

  6. React Hooks核心原理与实战

    React Hooks核心原理与实战 一.Hooks的优点 1.1 Hooks的含义 1.2 优点 二.常用的Hooks 2.1 useState 2.2 useEffect 2.3 useCallb ...

  7. 一起手写Vue3核心模块源码,掌握阅读源码的正确方法

    最近和一个猎头聊天,说到现在前端供需脱节的境况.一方面用人方招不到想要的中高级前端,另一方面市场上有大量初级前端薪资要不上价. 特别是用 Vue 框架的,因为好上手,所以很多人将 Vue 作为入门框架 ...

  8. 【springboot】手写SpringBoot核心流程

    通过手写模拟实现一个Spring Boot,就能以非常简单的方式就能知道Spring Boot大概是如何工作的. 工程与依赖 建一个工程,两个Module: spring-boot模块:表示sprin ...

  9. 手写识别底层原理_LinkedList底层原理和手写单链表

    2.1 单链表技能点 · 认识单链表 o 特点 数据元素的存储对应的是不连续的存储空间,每个存储结点对应一个需要存储的数据元素. 每个结点是由数据域和指针域组成. 元素之间的逻辑关系通过存储节点之间的 ...

最新文章

  1. gridcontrol 控件的用法
  2. 利用计算机诊断ct故障,计算机在CT室工作中的应用及管理
  3. 机器学习-吴恩达-笔记-4-神经网络描述
  4. magento添加面包屑
  5. C语言经典例23-输出菱形图案
  6. 快速生成数据库文档--screw
  7. 腾讯程序员与医生相恋,却被女方父母拆散,你们不能在一起
  8. 从存活了1441年的企业,我们能学到什么?
  9. PHP+MYSQL【学生信息管理系统】(极简版)
  10. python_误差分析
  11. 华为云MVP周峥:气象预报是个技术活,大数据、超算、AI,缺一不可
  12. unity3d 地面印花_Unity3D 中的贴花效果 – 苍白的茧
  13. 前端小程序,h5,浏览器,app, doc,.docx,.ofd,.PDF,.WPS以及Office文档的在线解析预览方式
  14. 论文翻译:LP-3DCNN: Unveiling Local Phase in 3D Convolutional Neural Networks
  15. 设计模式 - 创建型模式_工厂方法模式
  16. 下载FATSQ,读取10条序列并计算每条序列的长度和GC含量
  17. 数学 计算机 生物学,数据:中国高校数学、物理、化学、生物、计算机5大学科实力排名!...
  18. case when的判断顺序_case when
  19. Filecoin节点部署
  20. 我的世界java转模组基岩,《我的世界》无模组激光门!瞬间就能粉碎基岩,凋灵也要被秒杀?...

热门文章

  1. 【综合】体育比赛高手榜
  2. 元空间不足java.lang.OutOfMemoryError: PermGen space 错误的原因及解决方法
  3. php 字符串函数 教程_最全的php字符串处理函数
  4. matlab学习——北斗卫星信号分析
  5. 盏茶python(五) 函数
  6. Node——express模块中的req,res参数
  7. 欧阳萍听口班(上)——笔记+学习记录
  8. Windows版Git在进行git代码的时候出现报错
  9. 如何压缩png大小但不不失真?
  10. android跑马灯有时候不跑