fix(docs): hoist FitOnResize out of FlowDiagram render

Defining FitOnResize inside the parent render gave it a new component
identity on every parent render, forcing React to unmount/remount it
and tear down the ResizeObserver each time. Hoist it to module scope
and pass useReactFlow in as a prop. Also drop the unused instanceRef.
This commit is contained in:
John Fawcett
2026-05-13 12:07:16 -05:00
parent 25ae095944
commit 691b228b9e
@@ -3,6 +3,33 @@
import React, { useState, useEffect, useRef } from "react"
import { diagrams } from "./diagrams"
/**
* Re-fits the viewport whenever the React Flow container resizes.
* Defined at module scope so its component identity is stable across
* re-renders of FlowDiagram (otherwise React would unmount/remount it
* on every parent render and tear down the ResizeObserver each time).
*/
function FitOnResize({
useReactFlow,
}: {
useReactFlow: typeof import("@xyflow/react").useReactFlow
}) {
const { fitView } = useReactFlow()
const containerRef = useRef<HTMLDivElement | null>(null)
useEffect(() => {
const el = containerRef.current?.closest(".react-flow") as HTMLElement | null
if (!el) return
const observer = new ResizeObserver(() => {
fitView({ padding: 0.15 })
})
observer.observe(el)
return () => observer.disconnect()
}, [fitView])
return <div ref={containerRef} style={{ display: "none" }} />
}
/**
* FlowDiagram renders an interactive React Flow diagram.
* Loaded lazily to avoid bundling the entire @xyflow/react library on pages that don't use it.
@@ -15,7 +42,6 @@ import { diagrams } from "./diagrams"
export function FlowDiagram({ name, height = "400px" }: { name: string; height?: string }) {
const [mod, setMod] = useState<typeof import("@xyflow/react") | null>(null)
const [cssLoaded, setCssLoaded] = useState(false)
const instanceRef = useRef<any>(null)
useEffect(() => {
Promise.all([
@@ -69,23 +95,6 @@ export function FlowDiagram({ name, height = "400px" }: { name: string; height?:
const { ReactFlow, Background, BackgroundVariant, useReactFlow, ReactFlowProvider } = mod
const FitOnResize = () => {
const { fitView } = useReactFlow()
const containerRef = useRef<HTMLDivElement | null>(null)
useEffect(() => {
const el = containerRef.current?.closest(".react-flow") as HTMLElement | null
if (!el) return
const observer = new ResizeObserver(() => {
fitView({ padding: 0.15 })
})
observer.observe(el)
return () => observer.disconnect()
}, [fitView])
return <div ref={containerRef} style={{ display: "none" }} />
}
return (
<figure style={{ margin: "24px 0" }}>
<div
@@ -118,7 +127,7 @@ export function FlowDiagram({ name, height = "400px" }: { name: string; height?:
style={{ background: "#08080c" }}
>
<Background variant={BackgroundVariant.Dots} color="rgba(248,160,32,0.15)" gap={20} size={1} />
<FitOnResize />
<FitOnResize useReactFlow={useReactFlow} />
</ReactFlow>
</ReactFlowProvider>
</div>