【react】手写常用hooks

hooks在内存中是用链表进行存储的。
第一次渲染的时候,遍历组件,将各个hooks通过索引号index存储
再次渲染的时候,再次遍历,直接从索引号index里拿出既可

这也是为什么hooks不能写在if或循环语句中的原因

1.useState

  let hookStates=[]//用于存储hooks的数组
  let stateIndex=0 //用于指向hooks的索引号index
  function useState(initState){
    hookStates[stateIndex]=hookStates[stateIndex] || initState//第一次渲染(执行到useState)值为initState,再次渲染(执行到useState)值从数组中拿
    let currentIndex=stateIndex//通过闭包把当前index保存下来,不然的话执行setState的时候index不是当前值(已经加了很多次了)
    function setState(val){
      hookStates[currentIndex]=val//替换对应位置的值,也就是更改对应位置hookstate中保存的值
      render()
    }
    return [hookStates[stateIndex++],setState]
  }
  const root = ReactDOM.createRoot(document.getElementById('root'));
  function render(){
    stateIndex=0//每次渲染index都是从0开始的
  	root.render(<App />)
  }
  //const [count, setCount] = useState(1)

2.useMemo

function useMemo(callback,dependences){
    if(hookStates[stateIndex]){//再次渲染(执行到useMemo)
      let [lastMemo,lastDependences] = hookStates[stateIndex]//比较依赖项是否发生改变。如果没有直接返回lastMemo即可,如果改变了,就要生成新的对象
      let same = dependences.every((item,index)=>{return item === lastDependences[index]})
      if(same) {
        stateIndex++;
        return lastMemo;
      }
      else {
        hookStates[stateIndex++]=[callback(),dependences]
        return callback()
      }
    }
    else{//第一次渲染(执行到useMemo)
      hookStates[stateIndex++]=[callback(),dependences]//第一次是将回调的值和依赖项存进数组中
      return callback()
    }
  }

3.useCallback
和usememo一样,只不过usememo缓存的是值,usecallback缓存的是函数

function useCallback(callback,dependences){
    if(hookStates[stateIndex]){//再次渲染(执行到useMemo)
      let [lastCallback,lastDependences] = hookStates[stateIndex]//比较依赖项是否发生改变。如果没有直接返回lastMemo即可,如果改变了,就要生成新的对象
      let same = dependences.every((item,index)=>{return item === lastDependences[index]})
      if(same) {
        stateIndex++;
        return lastCallback;
      }
      else {
        hookStates[stateIndex++]=[callback,dependences]
        return callback
      }
    }
    else{//第一次渲染(执行到useMemo)
      hookStates[stateIndex++]=[callback,dependences]//第一次是将回调的值和依赖项存进数组中
      return callback
    }
  }

4.useEffect

useEffect解决函数式组件中,绑定事件、操作dom、定时器等一系列副作用

function useEffect(callback,dependences){
    if(hookStates[stateIndex]){//再次渲染(执行到useEffect)
      let [lastDestory,lastDependences] = hookStates[stateIndex]
      if(lastDependences.length){//如果有依赖项
        let same = dependences.every((item,index)=>item===lastDependences[index])
        if(same){//如果依赖项没变,直接跳过
          stateIndex++
        }
        else {//如果依赖项改变了,再更新
          lastDestory && lastDestory() //如果有销毁函数则执行
          hookStates[stateIndex++]=[callback(),dependences]
        }
      }else{//如果依赖项为空,直接跳过
        stateIndex++
      }

    }
    else{//第一次渲染(执行到useEffect)
      hookStates[stateIndex++]=[callback(),dependences]//保存销毁函数(callback中的return函数)和依赖项
    }
  }

5.useReducer

和useState非常相似

function useReducer(reducer,initState){
    hookStates[stateIndex] = hookStates[stateIndex] || initState
    let currentIndex = stateIndex
    function dispatch(action){
      hookStates[currentIndex] =reducer(hookStates[currentIndex],action)
      render()
    }
    return [hookStates[stateIndex++],dispatch]

  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值