Community JavaScript Snippet
The "Component Switch" Pattern I Use Instead of Big Render Trees
Big if/else ladders that pick a component by a tag are unreadable by the third branch. The pattern I use instead is a tiny lookup registry. Three accordions on shipping it.
The "Component Switch" Pattern I Use Instead of Big Render Trees
Big if/else ladders that pick a component by a tag are unreadable by the third branch. The pattern I use instead is a tiny lookup registry. Three accordions on shipping it.
By @diegonguyen
April 9, 2026
·
Updated May 18, 2026
780 views
25
4.5 (8)
Once I started writing this pattern, I stopped writing the if/else version. The registry is the entire surface area: every new view type is one line in the object, and the switch component has no behaviour beyond "look it up, render it, pass the rest of the props". Spreading the props rather than enumerating them is what keeps the switch generic; if a future view needs an extra prop, you just add it at the call site. The null return on an unknown tag is a deliberate choice: silently rendering nothing is the right behaviour during a feature flag rollout where the new tag has not landed yet, and the next accordion handles the strict variant for cases where you want a hard error instead.
The cost of the basic registry is that every view ships in the initial bundle. For three views that is fine; for thirty it is the wrong default. Wrapping each value in React.lazy(() => import('./Foo')) makes each view its own chunk, and the bundler only fetches the chunks the user actually triggers. The Suspense wrapper is what handles the in-flight state, and per-tag fallback strings are the easiest way to give each view a useful skeleton without writing component-specific loading UI. The trade-off is one network round-trip on first use of each tag; pair this with the preload-on-hover trick from the route-splitting snippet if the latency is visible.
Soft-failing in production and hard-failing in development is the trade-off that has held up best for me. A typo in a tag prop is a bug, and the only thing worse than a missing component is one that disappears silently and stays missing for two release cycles. Throwing in dev surfaces the bug at the call site, the error boundary catches it, and the message names the valid tags so the fix is one keystroke. Production logs the same message and renders a small [unknown view] placeholder so an outage in one tag does not nuke the whole page. If you are on TypeScript, the registry shape pays an additional dividend: typing the registry as Record<Tag, ComponentType<PropsForTag>> lets the type-checker prove the switch handles every tag, which is the discriminated-union mental model the explanation in the breakdown alludes to.
