React學習筆記 - useState解析
阿新 • • 發佈:2021-11-24
引入
對於函式元件
const App = props => {
const [n, setN] = useState(0)
//...
}
在setN
執行後:
n
不會被setN
改變(重要!)- 會觸發UI更新,
App()
再次執行,再次useState(0)
時,得到n
的值不同
分析:
setN
將n
的新值存入一箇中間變數state
useState
從state
讀取n
的最新值
模擬實現React.useState
v 1.0
用一個全域性變數_state
儲存n
的值
let _state
const useState2 = (initialValue)=>{
_state = _state === undefined? initialValue: _state //判斷_state是否存在
const setState = (newValue)=>{
_state = newValue
render()
}
return [_state, setState]
}
const render = ()=>{ //模擬實現重渲染,原始碼並非如此
ReactDOM.render(<App />, rootElement)
}
這樣在每次呼叫useState2(0)
的時候,都能使n
得到最新的值。
問題:只能設定一個數據,有多個數據怎麼辦?
v 2.0
改進思路:將_state
做成陣列,按順序儲存資料
let _state = []
let index = 0
const useState2 = (initialValue)=>{
const currentIndex = index
const setState = (newValue)=>{
_state[currentIndex] = newValue
render()
}
index++
return [_state[currentIndex], setState]
}
const render = ()=>{
index=0 //每次渲染前重置index
ReactDOM.render(<App />, rootElement)
}
【陣列方案的缺陷】
每次執行App()
時,設定資料的順序必須完全一樣,因此React
規定useState
不能用在if
語句中
【目前的問題】
App
元件用了_state
和index
,其他元件怎麼辦?
【解決方法】
將_state
和index
放在元件對應的虛擬DOM上(略)
總結
-
每個函式元件對應一個 React 節點,上面有
state
和index
-
useState
按其被呼叫順序讀取state[index]
-
setState
會修改state
,並觸發更新
問題:每次重渲染會產生新的n
,怎樣才能做到每次渲染都是同一個n
如何每次使用相同的n
(重要!)在 React 中,不推薦這樣做,可以改用 Vue 3
但 React 通過某些方法也能做到,可用useRef
或者useContext
(存疑)
useRef
useRef
常用於對元素進行引用,但也可以用於此場景,用它宣告一個數據nRef
:
const nRef = useRef(0) //它是一個物件:{current: 0}
useRef
使得在每次重渲染時,nRef
均為同一個物件,指向的地址固定。
但問題在於,對nRef
進行修改不會觸發重渲染,可以再引入一個setState
函式,用它強制更新
const update = useState(null)[1] //呼叫update,傳入新的值,會觸發更新
【完整示例】
const App = props => {
const nRef = React.useRef(0)
const update = React.useState(null)[1]
return (
<div>
{nRef.current}
<button onClick={()=>{
nRef.current++
update(nRef.current)
}}>+1</button>
</div>
)
}
useContext
context 的特點是可以跨層級傳遞資料給後代元件。
首先建立一個context
const myContext = React.createContext(null)
然後,在<myContext.Provider></myContext.Provider>
包圍的任何子元件中,都可以使用這個context
const App = props => {
return (
<myContext.Provider value={/* 傳入資料 */}>
<Child />
</myContext.Provider>
)
}
const Child = props => {
const a = React.useContext(myContext) //a即為以上由value傳入的資料
return (
<div>hi</div>
)
}
作者:茶葉淡
連結:https://juejin.cn/post/6890086834610077704
來源:稀土掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。