react hook 的useState实现方法

参考文章链接:https://www.bilibili.com/video/BV1aT4y1Y7Ax/?spm_id_from=333.337.search-card.all.click&vd_source=a5c30ef5d621e43c464eaded78548b9e

import ReactDOM from 'react-dom' //reactDOM , react 17.x支持,18.x不支持
import App from '../App';

const myReact = (() => { 
  let _state
  const useState = (init) => { 
    _state =  _state === undefined ? init : _state //每次render的时候都会重新调用useState,此次state不是初始值时,应该赋予他改变后的值
    function _setState(params) {
      if (typeof params === 'function') { //set*函数可以接收一个函数,函数的返回值作为新的改变值
        _state = params()
      } else { 
        _state = params
      }
      render()
    }
    return [_state,_setState]
  }
  function render() { //render 函数,每次调用set函数时刷新页面
    ReactDOM.render(
      <App />,
      document.querySelector('#root')
    )
  }
  return {
    useState
  }
})() //函数自调用

const { useState } = myReact

function UseMystate(props) {
  const [count,setCount] = useState(0)
  return (
    <div className="demo">
      <p>{count}</p>
      <button onClick={() => { setCount(count+1)}}>add 1</button>
      <button onClick={() => { setCount(count - 1) }}>reduce 1</button>
    </div>
  )
}
export default UseMystate

升级版本

import ReactDOM from 'react-dom' //reactDOM , react 17.x支持,18.x不支持
import App from '../App';

const myReact = (() => { 
  /*
    states 和 stateSetters初始值为空数组,为了存放每次初始化的值和更新后的值
    页面可能有多个useState,那么就需要将多个useState调用后的值存放在有序数组中,
    并且数组的初始index为0,每次调用useState时,index++
  */
  const states = [], stateSetters = [] 
  let stateIndex = 0
  /**
   * 创建state,如果第一次创建,则使用useState传递的初始值,如果是更新后的值,则去states 数组中取值
   * @param {*} init 初始值
   * @param {*} stateIndex 初始下标
   * @returns 返回值是创建好的新的state值
   */
  function createState(init,stateIndex) {
    return states[stateIndex] === undefined ? init : states[stateIndex]
  }
  /**
   * 创建state更新函数,每次调用更新函数的时候都很调用render()函数来更新页面
   * @param {*} stateIndex 返回更新函数列表的下标
   * @returns 更新state的函数,该函数接受一个参数,参数可以是function也可以是其他类型
   */
  function createStateSetters(stateIndex) {
    return function (newState) {
      if (typeof newState === 'function') {
        states[stateIndex] = newState(states[stateIndex])
      } else { 
        states[stateIndex] = newState
      }
      render()
    }
  }
  /**
   * useState函数,_state从states中取值,取不到的话就用初始传入的值,_setState从stateSetters列表中取,每次调用useState时,index++
   * @param {*} initData useState的初始值,可以是function,也可以是其他值
   * @returns [] 返回一个数组,数组第一项存放初始化的值和更新后的值,第二项存放更新这个值的方法
   */
  const useState = (initData) => {
    states[stateIndex] = createState(initData, stateIndex)
    if (!stateSetters[stateIndex]) { 
      stateSetters.push(createStateSetters(stateIndex))
    }
    const _state = states[stateIndex],
      _setState = stateSetters[stateIndex]
    
    stateIndex++ 
    return [_state,_setState]
  }
  /**
   * render函数,更新页面,每次调用时,stateIndex都会初始化为0
   */
  function render() { //render 函数,每次调用set函数时刷新页面
    stateIndex = 0
    ReactDOM.render(
      <App />,
      document.querySelector('#root')
    )
  }
  return {
    useState
  }
})() //函数自调用


const { useState } = myReact

function UseMystate(props) {
  const [count,setCount] = useState(0)
  const [flag,setFlag] = useState(false)

  return (
    <div className="demo">
      <p>{count}</p>
      <p>123</p>
      <button onClick={() => { setCount(count+1)}}>add 1</button>
      <button onClick={() => { setCount(count - 1) }}>reduce 1</button>
      <p>{ flag ? '打开状态' : '关闭状态'}</p>
      <button onClick={() => { setFlag(flag => flag = !flag) }}>{ flag ? '关' : '开'}</button>
    </div>
  )
}
export default UseMystate
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值