React学习笔记 - useState解析
引入
对于函数组件
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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。