Components
Understanding StatelessComponent and StatefulComponent
Components are the building blocks of Nocterm apps. This guide explains the two types of components and when to use each.
StatelessComponent
A StatelessComponent describes a UI that doesn't change over time. It takes input through its constructor and returns a component tree from its build() method.
Use stateless components when your UI depends only on the component's properties, not on changing state.
Example
Here's a simple greeting component:
class Greeting extends StatelessComponent {
const Greeting({required this.name, super.key});
final String name;
@override
Component build(BuildContext context) {
return Text('Hello, $name!');
}
}
Usage:
Greeting(name: 'Alice')
Every time you use this component with name: 'Alice', it displays "Hello, Alice!". The component itself never changes—only its input changes.
When to use StatelessComponent
Use stateless components when:
- The UI depends only on constructor parameters
- You don't need to track changing state
- The component just transforms data into UI
Examples:
- Display components that show data (labels, headers, formatted text)
- Layout wrappers that arrange children
- Reusable UI patterns that don't change
StatefulComponent
A StatefulComponent describes UI that changes over time. It creates a State object that holds mutable state and rebuilds the UI when state changes.
Use stateful components when your UI needs to change in response to user input, timers, or other events.
Example
Here's a toggle component:
class Toggle extends StatefulComponent {
const Toggle({super.key});
@override
State<Toggle> createState() => _ToggleState();
}
class _ToggleState extends State<Toggle> {
bool _isOn = false;
@override
Component build(BuildContext context) {
return Focusable(
focused: true,
onKeyEvent: (event) {
if (event.logicalKey == LogicalKey.space) {
setState(() {
_isOn = !_isOn;
});
return true;
}
return false;
},
child: Text(_isOn ? '[X] On' : '[ ] Off'),
);
}
}
The _isOn field holds state that changes when the user presses space. Calling setState() tells Nocterm to rebuild the UI.
Component and State separation
Stateful components split into two parts:
- Component (immutable): Configuration that can be rebuilt
- State (mutable): Internal state that persists across rebuilds
The component is your configuration. The state is where you store changing data.
When to use StatefulComponent
Use stateful components when:
- You need to track changing values (counters, toggles, form input)
- You respond to user interaction
- You use timers or async operations
- You need lifecycle methods
The build method
Both component types have a build() method that returns the UI:
@override
Component build(BuildContext context) {
return Text('Your UI here');
}
Nocterm calls build() when:
- The component first appears
setState()is called (stateful components)- The parent component rebuilds
Keep build() fast. It may be called frequently.
Component tree
Components form a tree structure. Each component can have children, and those children can have their own children.
Example tree:
Container
└─ Column
├─ Text('Title')
├─ SizedBox(height: 1)
└─ Row
├─ Text('Left')
└─ Text('Right')
When you write:
Container(
child: Column(
children: [
Text('Title'),
SizedBox(height: 1),
Row(
children: [
Text('Left'),
Text('Right'),
],
),
],
),
)
Nocterm builds this tree. Changes propagate down the tree—if Container rebuilds, its children rebuild too.
Keys
Keys help Nocterm identify specific components in the tree. Use keys when you need to preserve state or distinguish between components of the same type.
ValueKey
Use ValueKey to identify components by a unique value:
ListView(
children: [
for (var item in items)
ItemWidget(
key: ValueKey(item.id),
item: item,
),
],
)
Without keys, Nocterm might reuse the wrong component's state when the list changes.
GlobalKey
Use GlobalKey to access a component's state from anywhere:
final formKey = GlobalKey<FormState>();
// Later, access the state:
formKey.currentState?.validate();
Global keys are rare in most apps. You usually manage state through normal parent-child communication.
When to use keys
Use keys when:
- Reordering lists or collections
- Distinguishing between components of the same type
- Accessing a component's state from outside its tree
Most components don't need keys. Only add them when you encounter issues with state preservation or component identity.
Next steps
- Building UIs - Compose components into interfaces
- State Management - Learn more about managing state