diff --git a/src/content/learn/synchronizing-with-effects.md b/src/content/learn/synchronizing-with-effects.md index c9c41ca6c5..3f19a82233 100644 --- a/src/content/learn/synchronizing-with-effects.md +++ b/src/content/learn/synchronizing-with-effects.md @@ -598,6 +598,33 @@ input { display: block; margin-bottom: 20px; } 下面提供一些常用的 Effect 应用模式。 + + +#### Don't use refs to prevent Effects from firing {/*dont-use-refs-to-prevent-effects-from-firing*/} + +A common pitfall for preventing Effects firing twice in development is to use a `ref` to prevent the Effect from running more than once. For example, you could "fix" the above bug with a `useRef`: + +```js {1,3-4} + const connectionRef = useRef(null); + useEffect(() => { + // 🚩 This wont fix the bug!!! + if (!connectionRef.current) { + connectionRef.current = createConnection(); + connectionRef.current.connect(); + } + }, []); +``` + +This makes it so you only see `"✅ Connecting..."` once in development, but it doesn't fix the bug. + +When the user navigates away, the connection still isn't closed and when they navigate back, a new connection is created. As the user navigates across the app, the connections would keep piling up, the same as it would before the "fix". + +To fix the bug, it is not enough to just make the Effect run once. The effect needs to work after re-mounting, which means the connection needs to be cleaned up like in the solution above. + +See the examples below for how to handle common patterns. + + + ### 控制非 React 组件 {/*controlling-non-react-widgets*/} 有时需要添加不是使用 React 编写的 UI 小部件。例如,假设你要向页面添加地图组件,并且它有一个 `setZoomLevel()` 方法,你希望调整缩放级别(zoom level)并与 React 代码中的 `zoomLevel` state 变量保持同步。Effect 看起来应该与下面类似: