Context & Provider Mistakes
Generated from
.agents/rules/anti-patterns.md(the same source as MCPget_anti_patterns). Each entry is a real mistake + its fix; where a detector code is listed, the linter /pyreon doctor/ MCPvalidatecatches it automatically.
A component reading context bare while sibling hooks use a fallback
Route every consumer of a context+singleton pair through one resolver.
@pyreon/routerhooks andRouterLinkImplresolve throughgetActiveRouter()(context, then the active router). A bareuseContextread made<RouterLink>render a#/pathhref and swallow clicks aftersetActiveRouter(router)with no provider.A component that cannot resolve its dependency degrades to native behaviour (plain
href, unintercepted click, dev warning). Guard-bails run beforepreventDefault().Test:
packages/core/router/src/tests/link-dx.test.ts.
Destructuring context values
const { mode } = useContext(ctx) fires provider getters once. Keep the object and read ctx.mode inside reactive scopes.
Static provide for dynamic values
provide(ctx, "dark") is static. Provide an object with getters or an accessor: provide(ModeCtx, () => modeSignal()).
signal(newValue) to write
signal(5) reads and ignores the argument. Use signal.set(5) or signal.update(n => n + 1). Dev mode warns; the detector flags X(value) where X is a signal(...)/computed(...) const.
Detected by: signal-write-as-call — surfaced by @pyreon/lint / pyreon doctor / MCP validate.
onClick={undefined}
A nullish handler is legal and ignored (applyEventProp in runtime-dom/src/props.ts returns early for non-functions and warns only for wrong types).
onClick={cond ? handler : undefined}is the intended pattern.The risk is a silent dead control when a handler you expected is
undefined. The detector flags only the literalonClick={undefined}(omit the attribute instead).
Detected by: on-click-undefined — surfaced by @pyreon/lint / pyreon doctor / MCP validate.
Pyreon-flavored helper components in compat-mode apps without nativeCompat()
The *-compat JSX runtimes wrap user components in wrapCompatComponent, so a helper using provide() / onMount() / onUnmount() / effect() at body scope runs outside Pyreon's setup frame and breaks on re-render.
Call
nativeCompat(MyHelper)from@pyreon/core(core/src/compat-marker.ts) so compat runtimes route it throughh(). Framework components (RouterView,PyreonUI,FormProvider, …) are already marked.Unit tests cannot see this (a single synchronous mount keeps context); the cpa-app-compat e2e suites (
e2e/cpa-app-*-compat.spec.ts) catch it.