Class ComponentAttribute
- Namespace
- Velvet
- Assembly
- Velvet.Docs.dll
Registers a functional component (static VNode XxxComp()) as a Velvet component.
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class ComponentAttribute : Attribute
- Inheritance
-
objectAttributeComponentAttribute
Remarks
A static method annotated with [Component] must:
- Return VNode and take no arguments (Render is parameterless)
- Access external state only through Hooks (UseStore / UseContext / UseState, etc.)
- Follow the Rules of Hooks — call hooks unconditionally, in a stable order, only inside Render. These are enforced at runtime (a violation throws System.InvalidOperationException), not by a compile-time analyzer
- Be referenced from a parent VNode tree as
V.Component(MyComp.Render)
Two independent memoization axes — Memoize (props-bail) and Compiler (build-time auto-memo); see each member.
Properties
- Compiler
Whether the build-time compiler transform — inner auto-memoization — is woven into this component. Default is
true: the transform caches the component's VNode construction keyed on the values flowing out of its hook calls (and its props), rebuilding only when one of those inputs changes — Dependencies states the branch each type takes, since the weaver keys on the same dependency comparison. Auto-memoization needs no opt-in: set this tofalseto opt out. The weaver also declines a component silently, with no diagnostic, where it finds a hook it cannot memoize safely, andVelvetCompilerILPostProcessor.WillProcessdecides which assemblies it reaches at all.Set to
falseto opt this component out of the transform, so its body then runs in full on every render. This is an escape hatch for the rare component whose render must not be cached; it is orthogonal to Memoize, which governs the props-bail axis at the reconcile boundary.
- DisplayName
Optional debug name used in hook-rule violation messages and other diagnostics in place of the default
"DeclaringType.MethodName"form. Whennullor empty, the default name is used.
- IsErrorBoundary
Whether this component behaves as an Error Boundary. Default is
false.
- Memoize
Opt-in props-bail: skip a parent-driven re-render when this component's props are shallow-equal to the previous render — the props bag compared member by member, each member decided by the per-type rule Dependencies states. A props value that is not a props bag — a value type, a string, a collection — is compared whole under that same rule instead of through a member set, so two distinct collections of equal content are a change. Any other value type is decided by its own
Equals, which reads what it holds, and then — on this path alone — thefloatanddoublefields it carries, directly or inside a value type it holds, are compared by raw bit pattern on top of that, so+0and-0in one of those are a change as twofloatmembers are. That last reading is not part of the cited rule and the dependency comparison does not take it, so the same pair reaching a hook as a dependency is unchanged.ComponentPropsComparerTestsis what fails if either half of the props answer stops holding, andObjectIsTestsif the dependency answer starts taking it. Default isfalse.This is a true opt-in gate: only a component with
Memoize = true(or one created viaV.Memowith a custom comparator) bails on shallow-equal props. A component without it re-renders whenever its parent re-renders; only an opted-in component skips a re-render on equal props.Unrelated to MemoizeMethodAttribute: that attribute drives per-method wrapping by the Source Generator, while this property is the per-component props-bail flag at the reconcile boundary. The shared
Memoizeroot is all the two have in common.