yewstack/yew · error

no ctx found

Error message

no ctx found

What it means

This panic is `use_context::<Theme>().expect("no ctx found")` in `ThemedButton` from Yew 0.22's contexts guide. `use_context` returns `Option<Theme>`: it finds the value only if some ancestor component rendered `<ContextProvider<Theme> context={...}>`. The guide places that provider inside `ThemeContextProvider` (contexts.mdx line 121), and the doc comment on `ThemedButton` states it must be a child of that provider — render it anywhere else and the expect panics.

Source

Thrown at website/versioned_docs/version-0.22/concepts/contexts.mdx:144

}

/// The toolbar.
/// This component has access to the context
#[component]
pub fn Toolbar() -> Html {
    html! {
        <div>
            <ThemedButton />
        </div>
    }
}

/// Button placed in `Toolbar`.
/// As this component is a child of `ThemeContextProvider` in the component tree, it also has access
/// to the context.
#[component]
pub fn ThemedButton() -> Html {
    let theme = use_context::<Theme>().expect("no ctx found");

    html! {
        <button style={format!("background: {}; color: {};", theme.background, theme.foreground)}>
            { "Click me!" }
        </button>
    }
}
```

### Step 2: Consuming context

#### Function components

`use_context` hook is used to consume contexts in function components.
See [docs for use_context](https://yew-rs-api.web.app/next/yew/functional/fn.use_context.html) to learn more.

#### Struct components

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Wrap the consuming tree in `<ContextProvider<Theme> context={(*ctx).clone()}>` — render through `ThemeContextProvider` exactly as the guide shows
  2. Verify provider and consumer reference the same `Theme` struct (same crate path, no duplicate definition)
  3. Degrade gracefully instead of panicking: `let theme = use_context::<Theme>().unwrap_or_default();` or `match` with a fallback theme
  4. In component tests, always mount `ThemedButton` inside the provider

Example fix

// before
pub fn ThemedButton() -> Html {
    let theme = use_context::<Theme>().expect("no ctx found");
    ...
}

// after — provide the context above the consumer
html! {
    <ContextProvider<Theme> context={Theme { background: "#282c34", foreground: "#61dafb" }}>
        <Toolbar>
            <ThemedButton />
        </Toolbar>
    </ContextProvider<Theme>>
}
Defensive patterns

Strategy: fallback

Validate before calling

// one accessor hook so the None case has a defined default
#[hook]
fn use_theme() -> Theme {
    use_context::<Theme>().unwrap_or_default()
}

// ensure the provider is rendered above consumers:
// <ContextProvider<Theme> context={...}> ... <ThemedButton/> ... </ContextProvider<Theme>>

Prevention

When it happens

Trigger: Rendering `<ThemedButton/>` outside a `ThemeContextProvider` subtree; the provider publishing a different type than `Theme` (e.g. a wrapper struct), so the type-directed lookup finds nothing; the provider unmounting on navigation while the button remains.

Common situations: Reusing the guide's `ThemedButton` in a new page/route that is not under the provider; refactors that move `ThemeContextProvider` deeper or into a sibling layout; renaming the context struct during upgrades so provider and consumer types diverge.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/5041ce3772b48d08. Report an issue: GitHub.