你可能正在寻找 useSyncExternalStore
[name|Friend], when you see a useEffect
that updates a useState
and returns a value, you might be looking for a useSyncExternalStore
. This is my current vendetta.
[name|Friend],当你看到一个更新 useState
并返回值的 useEffect
时,你可能在找的是 useSyncExternalStore
。这是我现在的执念。
Makes it easier to fix jank like this:
让修复这种卡顿变得更容易:
PS: you can read and share this online
PS:你可以 在线阅读并分享这篇文章
A common pattern
一个常见模式
A pattern I see a lot in our React code combines a state, an effect, and a subscription:
我在我们的 React 代码中经常看到一种模式,它把 state、effect 和订阅组合在一起:
function useSomeValue() {
const [value, setValue] = useState(0)
useEffect(() => {
const eventSource = getEventSource()
eventSource.subscribe((val) => setValue(val))
return () => {
eventSource.unsubscribe()
}
}, [])
return value
}
This is a custom hook that subscribes to an event source like a browser API, or a ResizeObserver, or a state machine. Sometimes includes refs to the DOM to measure things.
这是一个自定义 hook,用于订阅事件源,比如浏览器 API、ResizeObserver 或状态机。有时还会包含对 DOM 的 ref 以进行测量。
This works.
这能行。
The effect runs on mount, subscribes to a thing, updates state to trigger re-renders, and cleans up with an unsubscribe when the component unmounts. It's a pattern you're familiar with after writing React for a while and you easily spot what's happening.
该 effect 在挂载时运行,订阅某个东西,更新 state 以触发重新渲染,并在组件卸载时通过取消订阅进行清理。这是你在写 React 一段时间后熟悉的模式,你很容易就能看出发生了什么。
Can lead to jank with server rendering
在服务端渲染时可能导致卡顿
The problem is that React has to render your component 2+ times before it settles into what you wanted. First it renders with a default value, then the effect runs, then it re-renders when state updates.
问题是 React 必须渲染你的组件 2 次或更多次,才能稳定到你想要的状态。首先用默认值渲染,然后 effect 运行,接着在 state 更新时重新渲染。
What you saw in the gif above is a slow hydration process.
你在上面的 gif 中看到的是一个缓慢的 hydration 过程。
- Component rendered on server with default values
- 组件在服务器端以默认值渲染
- Couldn't subscribe to browser events because there's no browser (I haven't confirmed if effects run at all)
- 无法订阅浏览器事件,因为没有浏览器(我还没确认 effect 是否会运行)
- HTML showe...