Why ReactFlow Edges Disappear in Next.js (Two Subtle CSS and Context Bugs)

Published: (March 30, 2026 at 11:35 AM EDT)
4 min read
Source: Dev.to

Source: Dev.to

nareshipme

We were building a knowledge‑graph view — a React Flow canvas that shows topic chains and semantic links between video segments. Nodes rendered fine, but every time we loaded the view the edges (the connecting lines between nodes) were simply gone.

No errors in the console. Nodes in place. Just… no edges.

Below is the two‑bug chain that caused it.

Bug 1: overflow‑hidden creates a stacking context that clips SVG edges

The first culprit was this wrapper:

// GraphView.tsx — BEFORE

  

overflow: hidden does two things most people don’t think about:

  1. Clips content that overflows the box (the obvious thing).
  2. Creates a new stacking context.

React Flow renders its edges as an SVG layer that is absolutely positioned within the canvas container. When an ancestor has overflow: hidden, that SVG layer gets clipped—even if it’s technically within the visible bounds—because the stacking context changes how the browser composites layers.

Fix

Use overflow: clip instead:

// GraphView.tsx — AFTER
{/* overflow‑clip instead of overflow‑hidden: clips visually without creating a new
    stacking context that would cause React Flow's SVG edge layer to be invisible */}

  

overflow: clip behaves like overflow: hidden visually—content is clipped at the box boundary—but does not create a new stacking context. The SVG edge layer can now composite correctly.

This is one of those CSS properties that exists specifically because overflow: hidden has an unfortunate side effect that trips up complex rendering scenarios like SVG overlays, fixed‑positioned children, and canvas‑based UIs.

Bug 2: Next.js dynamic() imports need an explicit ReactFlowProvider

Even after fixing the overflow issue, edges were still missing in some cases. The second bug was more subtle.

React Flow uses React context internally. The <ReactFlow> component expects a ReactFlowProvider to be present somewhere up the tree. In most setups you either wrap your app/page in a provider, or rely on React Flow’s own internal provider being initialized before the component renders.

The problem: we were loading the graph component with Next.js dynamic():

// project/page.tsx
const VideoKnowledgeGraph = dynamic(
  () => import('@/components/VideoKnowledgeGraph'),
  { ssr: false }
);

With dynamic(), the component is loaded in a separate chunk and initialized asynchronously. When this happens, the React Flow context—specifically the provider that manages the internal store for nodes, edges, and the SVG renderer—can be absent or not yet initialized at the time the SVG edge layer tries to render.

Result: nodes render (they don’t depend on the internal edge store in the same way), but edges don’t.

Fix

Explicitly wrap the dynamically imported component in <ReactFlowProvider>:

// VideoKnowledgeGraph.tsx — AFTER
import { ReactFlow, ReactFlowProvider, Background, Controls } from '@xyflow/react';

export default function VideoKnowledgeGraph({ graph, ...rest }) {
  // …
  return (
    // ReactFlowProvider is required here because this component is loaded via Next.js
    // dynamic() import. Without an explicit provider, the React Flow context (including
    // the SVG edge renderer) can be missing, causing edges to not render.
    <ReactFlowProvider>
      <ReactFlow
        nodes={graph.nodes}
        edges={graph.edges}
        // …other props
      >
        <Background />
        <Controls />
        {/* toolbar */}
        {/* …other UI */}
      </ReactFlow>
    </ReactFlowProvider>
  );
}

Rule of thumb: any React Flow component loaded via dynamic() should include its own ReactFlowProvider. Don’t assume the context will be present from a parent—async chunk loading makes the initialization order uncertain.

Why both bugs were needed to hide edges

Either bug alone might have been survivable:

BugPossible outcome
Stacking‑context issue onlyEdges might render in some browsers but get clipped in others
Missing provider onlyReact Flow could fall back to an ancestor provider if one existed

Together they compounded: the SVG layer wasn’t rendering at all (provider issue), and even if it had rendered, it would have been clipped (overflow issue).

When debugging React Flow edge visibility, check these two things first:

  1. Any ancestor with overflow: hidden? Switch to overflow: clip or overflow: visible.
  2. Is the component loaded dynamically? Wrap it in <ReactFlowProvider>.

Takeaway

overflow: hidden is one of CSS’s “does more than it says” properties—it creates a new stacking context that can interfere with SVG overlays, fixed‑positioned children, and canvas‑based UIs. When using libraries like React Flow that render edges in an SVG layer, prefer overflow: clip (or overflow: visible) unless you explicitly need the stacking‑context side effect. And always ensure the required context providers are present when loading components asynchronously with Next.js dynamic().

t creation. And when using React Flow with Next.js dynamic(), always provide the context explicitly rather than hoping it exists up the tree.

Both are easy one‑line fixes once you know what to look for. The hard part is knowing what to look for.

0 views
Back to Blog

Related posts

Read more »