Skip to content

Instantly share code, notes, and snippets.

@dongyuanxin
Last active August 9, 2020 09:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dongyuanxin/4281ee21eafdc0197d6ddea27bfbdbfd to your computer and use it in GitHub Desktop.
Save dongyuanxin/4281ee21eafdc0197d6ddea27bfbdbfd to your computer and use it in GitHub Desktop.
ReactHook的原理和TS实现
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();
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();
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