next属性形成链表连接在一起
function App() {
const [count, setCount] = useState(0)
// setCount((v) => v + 1) // 这里的 v 是上一次 count 更新的结果(每一次更新都是闭包),无论是直接更新还是函数式更新,因为都是上一次更新后的闭包
function handleClick() {
// setCount(count => count + 1) 函数式更新(preState)=> newState, preState 是之前的状态,可以解决非合成时间或者setTimeout/setInternal的状态不正确的问题。
setCount(count + 1) // 无效,也是因为闭包,因为每次 click 事件触发的时候都是运行这个函数,但是因为闭包的缘故,这个 count 始终是初始值
}
useLayoutEffect(() => {
document.getElementById('test').addEventListener('click', handleClick)
return () => removeEventListener('click', handleClick)
}, []) // 如果在依赖中添加了count, 那么也可以解决上面的问题。
useEffect(() => {
setTimeout(() => {
console.log(count) // 始终是 0,也是因为闭包。
}, 3000)
}, [])
return (
<div>
<p id="test">非合成事件或者 setTimeout setInternal 等异步函数</p>
</div>
)
}
简单的说就是把任务标记为非紧急的一次更新
const App = () => {
const { isPending, startTransition } = useTransition()
useEffect(() => {
startTransition(() => {
// 耗时任务
})
}, [xxx])
}
把 state 延迟生效
const App = () => {
const [count, setCount] = useState(0)
const debounceCount = useDeferredValue(count) // 跟防抖差不多的意思。比如 count 频繁变化,不会立即更改它以及依赖它的任务,等到合适的时机再把它更新成正确的值。
}
不同于 useEffect, 在 useLayoutEffect 里面可以访问 dom 节点。
类似 useLayoutEffect, 不过暂时无法访问 dom 节点的引用。一般只在 css-in-js 库中使用。一般用于提前注入 style 脚本。