共计 1847 个字符,预计需要花费 5 分钟才能阅读完成。
- 每次渲染都有独立的状态(State)
`function Demo() {
const initCount = 0
const [count, setCount] = useState(initCount)
return (
<div>
<h2>{count}</h2>
<button onClick={() => setCount(count + 1)}>count++</button>
</div>
)
}
`
每当用户点击一次按钮 都会从新触发 render 函数,每次 render 拿到的都是独立的状态
因为咱们生命 count 的值时应用 const,所以每次渲染拿到的 count 值是一个独立的常量。
- 每次渲染都有不同且独立的函数(Effect 函数)
`function Demo() {
const initCount = 0
const [count, setCount] = useState(initCount)
// 假如在 1s 内屡次点击按钮 这里打印的 count 值是什么?
useEffect(() => {
setTimeout(() => {
console.log(count) // 这里打印的会是以后这一次的 count 值,并不是最新的 count 值
}, 1000)
})
return (
<div>
<h2>{count}</h2>
<button onClick={() => setCount(count + 1)}>count++</button>
</div>
)
}
`
每次 count 值扭转,都会触发 render,组件从新渲染,所以每次都会生成对应的 useEffect 函数
而且咱们发现每次打印 count 的值拿到的都是以后轮次的 count 值(并不是最新的 count)
- useEffect 到底是怎么拿到最新的状态值的?
咱们晓得每次渲染都会触发 render,每次更新就会生成一个新的 Effect 函数,并且每一个 Effect 函数外面都有独立的 State,且只能拜访本人本次更新的 State。
所以用下面的例子,得出的论断就是:count 值其实不是在同一个 Effect 函数外面产生扭转,而是每一次的组件更新,都会生成一个保护着本次更新的 Effect 函数,在这个最新的 Effect 函数里就能够拜访到最新的 count 值。
- useEffect 返回的函数是如何进行清理工作的?
`function Demo() {
const initCount = 0
const [count, setCount] = useState(initCount)
useEffect(() => {
let timer = setTimeout(() => {
console.log(count)
}, 1000)
// 清理工作
return () => {
clearTimeout(timer)
}
})
return (
<div>
<h2>{count}</h2>
<button onClick={() => setCount(count + 1)}>count++</button>
</div>
)
}
`
假如用户点击了两次次按钮 当第一次点击的时候 count + 1 = 1,而后执行 clearTimout 革除本次的定时器?接着持续 count + 1 = 2 而后执行 clearTimeout 革除本次的定时器?
正确的程序应该是:当第一次点击 count + 1 = 1,而后 clearTimeout 会被提早执行,等到第二次点击的时候 count + 1 = 2 再执行上一次的 clearTimeout 而后以此类推... 问题来了 不是说 effect 函数只能拜访本次的 State 吗?那它怎么拿到上一次的 clearTimeout 并执行的?
其实很简略,就是 React 会帮你记住每次 effect 函数的 State(包含革除函数),它的确是只能读取本次更新的 State,只不过是提早执行了(把革除函数的执行机会放在 DOM 渲染实现后,在下一次 render 触发之前)
剩下的内容下期见吧,我累了,当初要去吃麦当劳补充一下能量 …
下期预报:useEffect 的第二个参数具体解析及应用,在开发中正当应用依赖(防止死循环、性能优化...)