Class ComponentAttribute
- Namespace
- Velvet
- Assembly
- Velvet.Docs.dll
Registers a static method returning VNode as a Velvet function component.
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class ComponentAttribute : Attribute
- Inheritance
-
objectAttributeComponentAttribute
Remarks
A static method annotated with [Component]:
- takes no parameter, mounted with
V.Component(MyComp.Render), or one props parameter, mounted withV.Component(MyComp.Render, props)orV.Memo; - reads what it renders from its props and its hooks — Compiler states what the build-time transform caches on;
- follows the Rules of Hooks: hooks are called unconditionally, in a stable order, and only while it renders.
Memoize (props-bail) and Compiler (build-time auto-memo) are its two independent memoization axes; see each member.
Properties
- Compiler
Whether the build-time compiler transform — inner auto-memoization — is woven into this component. Default is
true: the transform keys the component's VNode construction on its props and the values flowing out of its hook calls, compared as Dependencies states, and a render whose inputs all compare equal returns the cached tree instead of running the body. On such a render a difference that comparison does not see — a list mutated in place, a field a value type's ownEqualsignores — does not reach the tree, nor does anything else the body reads. The cache serves the component's own render; called as a plain method, the body runs uncached. Parts of the body are cached on their own as well: a call that builds a VNode, with the code that builds its arguments, is keyed on only the values it reads, so a render in which some inputs changed builds again only the parts that read them and keeps the rest by instance. The memoization guide states what keeps a part from being cached, and MemoizationReportAttribute records on each method what was left out. A component that takes props and calls no hook is keyed on its props alone, and left unwoven where it also sets Memoize; one with neither props nor a hook has nothing to key on and is left unwoven. Auto-memoization needs no opt-in: set this tofalseto opt out. The weaver does not key the body as a whole, with no diagnostic, where it finds a hook it cannot memoize safely, andVelvetCompilerILPostProcessor.WillProcessdecides which assemblies it reaches at all. A component whose body the weaver fails to process is left unwoven with a build warning naming it. A call whose target the build cannot enumerate — through an interface, or to a virtual method an override can replace — is cached with the rest of the body where it follows every hook call the body makes, and keeps the body from being keyed as a whole where it precedes one or sits inside a custom hook, even after that hook's ownUseState; the parts that do not read its result are still cached. Once such a call runs a hook while the body builds its tree, the component's body runs on every render from then on.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.Only a component with
Memoize = true, or one mounted withV.Memoand its comparer, skips a parent-driven render on props judged equal. Whether a component's body runs on a render that reaches it is Compiler's to say.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.