Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
title: Using React Context to Avoid Prop-Drilling
---

import CircuitPreview from "@site/src/components/CircuitPreview"

React Context is a powerful tool for sharing data across deeply nested components without having to pass props through every level of the tree. When building TypeScript-powered circuit design tools, context lets you centralize configuration and provide well-typed data to any component that needs it.

## When to use React Context
Expand Down Expand Up @@ -121,20 +123,6 @@ export const InstrumentPanel = () => (

Because every component inside the provider shares the same context, you can introduce additional consumers (for example, status displays or documentation overlays) without modifying intermediate components.

## Testing Context Consumers

When unit testing components that depend on the context, render them with the provider to supply the necessary data. Libraries like [`@testing-library/react`](https://testing-library.com/docs/react-testing-library/intro/) make this pattern straightforward:

```tsx
render(
<BoardSettingsProvider value={mockSettings}>
<ResistorList names={["R10"]} />
</BoardSettingsProvider>
)
```

This keeps tests realistic while preserving the benefits of type safety.

## Key Takeaways

- Define a context value type that captures the shared configuration.
Expand All @@ -143,3 +131,90 @@ This keeps tests realistic while preserving the benefits of type safety.
- Wrap only the subtree that needs the shared data, keeping providers focused and intentional.

With these patterns, React Context becomes a reliable way to manage shared state in your TypeScript tscircuit projects without the noise of prop drilling.

<CircuitPreview
hide3DTab
hidePCBTab
defaultView="schematic"
code={`import { ReactNode, createContext, useContext, useMemo } from "react"
Comment on lines +135 to +139

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import CircuitPreview before usage

The new <CircuitPreview …> block is referenced at the bottom of this guide but the file does not import the component anywhere after the front matter. MDX compilation will fail with ReferenceError: CircuitPreview is not defined when building the docs. Add import CircuitPreview from "@site/src/components/CircuitPreview" near the top so the interactive example renders correctly.

Useful? React with 👍 / 👎.


type BoardSettings = {
boardName: string
boardSize: { width: number; height: number }
defaultFootprints: {
resistor: string
capacitor: string
}
}

const BoardSettingsContext = createContext<BoardSettings | null>(null)

const BoardSettingsProvider = ({
children,
value,
}: {
children: ReactNode
value: BoardSettings
}) => {
const memoizedValue = useMemo(() => value, [value])

return (
<BoardSettingsContext.Provider value={memoizedValue}>
{children}
</BoardSettingsContext.Provider>
)
}

const useBoardSettings = () => {
const context = useContext(BoardSettingsContext)

if (!context) {
throw new Error("useBoardSettings must be used within a BoardSettingsProvider")
}

return context
}

const ResistorList = ({ names }: { names: string[] }) => {
const {
defaultFootprints: { resistor },
} = useBoardSettings()

return (
<group name="Resistors">
{names.map((name) => (
<resistor key={name} name={name} footprint={resistor} resistance="1k" />
))}
</group>
)
}

const DecouplingCapacitor = ({ name }: { name: string }) => {
const {
defaultFootprints: { capacitor },
} = useBoardSettings()

return <capacitor name={name} capacitance="10n" footprint={capacitor} />
}

export default function InstrumentPanel() {
return (
<BoardSettingsProvider
value={{
boardName: "Instrumentation Panel",
boardSize: { width: 50, height: 40 },
defaultFootprints: {
resistor: "0402",
capacitor: "0603",
},
}}
>
<board width="50mm" height="40mm" name="InstrumentPanel">
<ResistorList names={["R1", "R2", "R3"]} />
<DecouplingCapacitor name="C1" />
</board>
</BoardSettingsProvider>
)
}
`}
/>