参考文章链接: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