[React] Custom useState and useEffect hook

import { flushSync } from 'react-dom'
import { createRoot } from 'react-dom/client'

let hookIndex = 0
const states: Array<[any, (newState: any) => void]> = []
const INITIALIZATION = Symbol('INITIALIZATION')
const UPDATE = Symbol('UPDATE')
type Phase = typeof INITIALIZATION | typeof UPDATE
let phase = INITIALIZATION

/**
 * 1. Multiple useState problem
 * a. We need to use `INITIALIZATION` and `UPDATE symbol to keep track of the phase
 * b. We need a Hook id to keep track of the current hook
 * 	- ID will be from 0 and onwards
 *  - ID will be reset to 0 for each render
 */
function useState<T>(initialState: T) {
	const id = hookIndex++
	if (phase === INITIALIZATION) {
		states[id] = [
			initialState,
			(newState: T) => {
				states[id][0] = newState
				render(UPDATE)
			},
		]
	}

	return states[id] as [T, (newState: T) => void]
}

type EffectCallback = () => void
const effects: Array<{
	callback: EffectCallback
	deps?: any[]
	prevDeps?: any[]
}> = []

function useEffect(callback: EffectCallback, deps?: any[]) {
	const id = hookIndex++
	const prevDeps = effects[id]?.deps
	effects[id] = { callback, deps, prevDeps }
}

function Counter() {
	const [count, setCount] = useState(0)
	const [enabled, setEnabled] = useState(true)

	const increment = () => setCount(count + 1)
	const toggle = () => setEnabled(!enabled)

	useEffect(() => {
		console.log('efftivec')
	}, [enabled])

	return (
		<div className="counter">
			<button onClick={increment}>{count}</button>
			<button onClick={toggle}>{enabled ? 'Disable' : 'Enable'}</button>
		</div>
	)
}

const rootEl = document.createElement('div')
document.body.append(rootEl)
const appRoot = createRoot(rootEl)

function render(newPhase: Phase) {
	hookIndex = 0
	phase = newPhase

	flushSync(() => {
		appRoot.render(<Counter />)
	})

	for (const effect of effects) {
		if (!effect) continue

		const hasDepsChanged = effect.deps
			? !effect.deps.every((dep, i) => Object.is(dep, effect.prevDeps?.[i]))
			: true

		if (hasDepsChanged) {
			effect.callback()
		}
	}
}

render(INITIALIZATION)

 

posted @   Zhentiw  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2022-07-31 [Functional Programming] Make a flip and reverse functions
2021-07-31 [SAA + SAP] 13. S3
2020-07-31 [XState] History state
2020-07-31 [XState] Nested State
2018-07-31 [Angular] New in V6.1
2018-07-31 [Javascript] JavaScript赋值时的传值与传址
2017-07-31 [React Intl] Use Webpack to Conditionally Include an Intl Polyfill for Older Browsers
点击右上角即可分享
微信分享提示