Last active
August 9, 2020 09:16
-
-
Save dongyuanxin/4281ee21eafdc0197d6ddea27bfbdbfd to your computer and use it in GitHub Desktop.
ReactHook的原理和TS实现
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
const states: any[] = []; | |
let cursor: number = 0; | |
function useState<T>(initialState: T): [T, (newState: T) => void] { | |
const currenCursor = cursor; | |
states[currenCursor] = states[currenCursor] || initialState; | |
function setState(newState: T) { | |
states[currenCursor] = newState; | |
render(); | |
} | |
++cursor; | |
return [states[currenCursor], setState]; | |
} | |
const allDeps: any[][] = []; | |
let effectCursor: number = 0; | |
function useEffect(callback: () => void, deps: any[]) { | |
if (!allDeps[effectCursor]) { | |
allDeps[effectCursor] = deps; | |
++effectCursor; | |
callback(); | |
return; | |
} | |
const currenEffectCursor = effectCursor; | |
const rawDeps = allDeps[currenEffectCursor]; | |
const isChanged = rawDeps.some( | |
(dep: any, index: number) => dep !== deps[index] | |
); | |
if (isChanged) { | |
callback(); | |
} | |
++effectCursor; | |
} | |
function App() { | |
const [num, setNum] = useState<number>(0); | |
const [num2] = useState<number>(1); | |
// 每次点击按钮,都会触发 setNum 函数 | |
// 副作用检测到 num 变化,会自动调用回调函数 | |
useEffect(() => { | |
console.log("num update: ", num); | |
}, [num]); | |
// 只会在compoentDidMount时,触发一次 | |
// 副作用函数不会多次执行 | |
useEffect(() => { | |
console.log("num2 update: ", num2); | |
}, [num2]); | |
return ( | |
<div> | |
<div>num: {num}</div> | |
<div> | |
<button onClick={() => setNum(num + 1)}>加 1</button> | |
<button onClick={() => setNum(num - 1)}>减 1</button> | |
</div> | |
</div> | |
); | |
} | |
function render() { | |
ReactDOM.render(<App />, document.getElementById("root")); | |
cursor = 0; | |
effectCursor = 0; | |
} | |
render(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
const states: any[] = []; | |
let cursor: number = 0; | |
function useState<T>(initialState: T): [T, (newState: T) => void] { | |
const currenCursor = cursor; | |
states[currenCursor] = states[currenCursor] || initialState; | |
function setState(newState: T) { | |
states[currenCursor] = newState; | |
render(); | |
} | |
++cursor; | |
return [states[currenCursor], setState]; | |
} | |
function App() { | |
const [num, setNum] = useState<number>(0); | |
const [num2, setNum2] = useState<number>(1); | |
return ( | |
<div> | |
<div>num: {num}</div> | |
<div> | |
<button onClick={() => setNum(num + 1)}>加 1</button> | |
<button onClick={() => setNum(num - 1)}>减 1</button> | |
</div> | |
<hr /> | |
<div>num2: {num2}</div> | |
<div> | |
<button onClick={() => setNum2(num2 * 2)}>扩大一倍</button> | |
<button onClick={() => setNum2(num2 / 2)}>缩小一倍</button> | |
</div> | |
</div> | |
); | |
} | |
function render() { | |
ReactDOM.render(<App />, document.getElementById("root")); | |
cursor = 0; | |
} | |
render(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
function render() { | |
ReactDOM.render(<App />, document.getElementById("root")); | |
} | |
let state: any; | |
function useState<T>(initialState: T): [T, (newState: T) => void] { | |
state = state || initialState; | |
function setState(newState: T) { | |
state = newState; | |
render(); | |
} | |
return [state, setState]; | |
} | |
function App() { | |
const [num, setNum] = useState<number>(0); | |
return ( | |
<div> | |
<div>num: {num}</div> | |
<div> | |
<button onClick={() => setNum(num + 1)}>加 1</button> | |
<button onClick={() => setNum(num - 1)}>减 1</button> | |
</div> | |
</div> | |
); | |
} | |
render(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment