useState
- 熟悉hooks的都知道窍奋,最常用的useState
- 大概用法
function App() {
const [x, setX] = useState(0)
return <div>
<h1>{x}</h1>
<button onClick={() => setX(x + 1)}>+1</button>
</div>
}
簡(jiǎn)單的實(shí)現(xiàn)一個(gè)useState
- 先模擬入?yún)⒑统鰠?/li>
const rootElement = document.getElementById("root");
const render = () => {
ReactDOM.render(<App/>, root)
}
const useState = (initialValue) => {
function setState(newState) {
render()
}
return [state, setState]
}
function App() {
const [n, setN] = useState(0);
return (
<div className="App">
<h1>{n}</h1>
<button onClick={() => setN(n + 1)}>+1</button>
</div>
);
}
- 函數(shù)是存不住變量的,每次重新觸發(fā)就會(huì)出現(xiàn)一個(gè)新的值险耀,所以我們的state需要一個(gè)全局的state。
- 當(dāng)完成下面這個(gè)玖喘,一個(gè)簡(jiǎn)單的useState就完成了甩牺。
- 可是它有bug,如果用到多個(gè)useState累奈,他們共用的是一個(gè)state贬派,那么就完蛋了,所以要改造一下澎媒。
let state;
const render = () => {
ReactDOM.render(<App/>, root)
}
const useState = (initialValue) => {
state = state === undefined ? initialValue : state
function setState(newState) {
state = newState
render()
}
return [state, setState]
}
- 把 state 初始化為一個(gè)數(shù)組搞乏,每次聲明一個(gè)useState時(shí)候就在存放一個(gè)值,并且用index去代表值戒努。
- 按照思路请敦,每次觸發(fā)useState就要 index + 1,代表要在state數(shù)組里面添加一個(gè)值储玫。
- 每次重新setState重新渲染時(shí)候侍筛,就要index歸0,不然會(huì)無(wú)限增大state這個(gè)數(shù)組撒穷。
let state = []
let index = 0
const render = () => {
index = 0
ReactDOM.render(<App/>, root)
}
const useState = (initialValue) => {
const currentIndex = index
state[currentIndex] = state[currentIndex] === undefined
? initialValue
: state[currentIndex]
function setState(newState) {
state[currentIndex] = newState
render()
}
index = index + 1
return [state[currentIndex], setState]
}
- 基本就完成了一個(gè)useState
- 運(yùn)行代碼
從簡(jiǎn)單例子匣椰,深入一點(diǎn)了解。
-
從簡(jiǎn)單的例子我們可以看出桥滨,react 對(duì) useState 標(biāo)識(shí)是用index去記錄的窝爪,所以u(píng)seState不能寫在 if 里面弛车,不然順序就識(shí)別不了齐媒,我們常常看到這么一行報(bào)錯(cuò)纷跛。
就是這個(gè)原因喻括,當(dāng)然react內(nèi)部的index是使用鏈表去實(shí)現(xiàn)的。
-
那么贫奠,每個(gè)組件的state聲明在哪里唬血? 其實(shí)它就聲明在虛擬dom里頭望蜡。
每次聲明一個(gè)組件時(shí)候,組件內(nèi)部就會(huì)生成一個(gè) memoizedState 和 index (真正名稱自己去查看)