Class-based components provide a structured way to create components with internal state and lifecycle methods. They extend the Component class from GlyphUI.
Basic Structure
A class component extends Component and implements a render() method:
import { h , Component } from "glyphui" ;
class HelloWorld extends Component {
constructor ( props ) {
super ( props , {
initialState: { greeting: "Hello, World!" }
});
}
render ( props , state ) {
return h ( "div" , {}, [
h ( "div" , { class: "greeting" }, [ state . greeting ])
]);
}
}
Constructor
The constructor receives props and passes configuration to the parent class:
class Counter extends Component {
constructor ( props ) {
super ( props , {
initialState: {
count: props . initialCount || 0
}
});
}
}
Always call super(props, { initialState }) before accessing this in the constructor.
The render() Method
The render() method is the only required method. It receives props, state, and emit as arguments:
render ( props , state , emit ) {
return h ( "div" , { class: "counter" }, [
h ( "h2" , {}, [ props . title || "Counter" ]),
h ( "div" , { class: "counter-value" }, [ state . count . toString ()]),
h ( "button" , {
on: { click : () => this . increment () }
}, [ "Increment" ])
]);
}
State Management
Initializing State
Set initial state in the constructor:
constructor ( props ) {
super ( props , {
initialState: {
count: 0 ,
message: "Ready" ,
items: []
}
});
}
Updating State with setState()
Use this.setState() to update state and trigger a re-render:
class Counter extends Component {
constructor ( props ) {
super ( props , {
initialState: { count: 0 }
});
}
increment () {
this . setState ({ count: this . state . count + 1 });
}
decrement () {
this . setState ({ count: this . state . count - 1 });
}
reset () {
this . setState ({ count: 0 });
}
render ( props , state ) {
return h ( "div" , {}, [
h ( "p" , {}, [ `Count: ${ state . count } ` ]),
h ( "button" , { on: { click : () => this . increment () } }, [ "Increment" ]),
h ( "button" , { on: { click : () => this . decrement () } }, [ "Decrement" ]),
h ( "button" , { on: { click : () => this . reset () } }, [ "Reset" ])
]);
}
}
setState() merges the new state with the existing state. Only the properties you pass will be updated.
Functional State Updates
setState() can also accept a function that receives the previous state:
addTodo () {
this . setState (( prevState ) => ({
todos: [ ... prevState . todos , newTodo ],
nextId: prevState . nextId + 1
}));
}
Lifecycle Methods
Class components provide lifecycle methods for different stages of a component’s life:
beforeMount()
Called right before the component is mounted to the DOM:
beforeMount () {
console . log ( "Component is about to mount" );
// Initialize data or prepare resources
}
mounted()
Called after the component has been mounted to the DOM:
class Clock extends Component {
constructor ( props ) {
super ( props , {
initialState: { time: new Date (). toLocaleTimeString () }
});
}
mounted () {
// Start a timer when component is mounted
this . timerID = setInterval (() => {
this . setState ({ time: new Date (). toLocaleTimeString () });
}, 1000 );
}
render ( props , state ) {
return h ( "div" , { class: "clock-display" }, [
h ( "span" , { class: "time" }, [ state . time ])
]);
}
}
Use mounted() for DOM manipulations, data fetching, or setting up subscriptions.
beforeUpdate(oldProps, newProps)
Called before the component is re-rendered due to new props:
beforeUpdate ( oldProps , newProps ) {
console . log ( "Props changed:" , oldProps , "->" , newProps );
// React to prop changes before render
}
updated(oldProps, newProps)
Called after the component has been updated:
updated ( oldProps , newProps ) {
if ( oldProps . userId !== newProps . userId ) {
this . fetchUserData ( newProps . userId );
}
}
beforeUnmount()
Called right before the component is unmounted:
beforeUnmount () {
// Clean up resources before component is destroyed
clearInterval ( this . timerID );
// Cancel pending requests, remove event listeners, etc.
}
unmounted()
Called after the component has been unmounted:
unmounted () {
console . log ( "Component has been removed from the DOM" );
}
Complete Example
Here’s a full example of a Todo application using class-based components:
import { h , Component } from "glyphui" ;
class TodoApp extends Component {
constructor () {
super ({}, {
initialState: {
currentTodo: "" ,
nextId: 3 ,
todos: [
{ id: 0 , text: "watch OOP vs FP video" },
{ id: 1 , text: "feed the cat" },
{ id: 2 , text: "publish framework" }
]
}
});
}
updateCurrentTodo ( currentTodo ) {
this . setState ({ currentTodo });
}
addTodo () {
const newTodo = {
id: this . state . nextId ,
text: this . state . currentTodo
};
this . setState ({
currentTodo: "" ,
nextId: this . state . nextId + 1 ,
todos: [ ... this . state . todos , newTodo ]
});
}
removeTodo ( id ) {
this . setState ({
todos: this . state . todos . filter ( todo => todo . id !== id )
});
}
render ( props , state ) {
return h ( "div" , { class: "todo-app" }, [
h ( "input" , {
type: "text" ,
value: state . currentTodo ,
on: {
input : ({ target }) => this . updateCurrentTodo ( target . value ),
keydown : ({ key }) => {
if ( key === "Enter" && state . currentTodo . length >= 3 ) {
this . addTodo ();
}
}
}
}),
h ( "button" , {
disabled: state . currentTodo . length < 3 ,
on: { click : () => this . addTodo () }
}, [ "Add" ]),
h ( "div" , { class: "todo-list" },
state . todos . map ( todo =>
h ( "div" , { key: todo . id , class: "todo-item" }, [
h ( "span" , {}, [ todo . text ]),
h ( "button" , {
on: { click : () => this . removeTodo ( todo . id ) }
}, [ "Done" ])
])
)
)
]);
}
}
Mounting Components
To mount a class component to the DOM:
const app = new TodoApp ();
app . mount ( document . getElementById ( "app" ));
Or use createComponent() when nesting components:
import { createComponent } from "glyphui" ;
render ( props , state ) {
return h ( "div" , {}, [
createComponent ( Counter , {
key: 1 ,
title: "Counter 1" ,
initialCount: 0
})
]);
}
When to Use Class Components
Use Class Components For
Complex state management
Lifecycle method requirements
Object-oriented patterns
Team familiarity with OOP
Consider Functional Components If
Simple presentational UI
Hooks-based state management
Functional programming style
Modern React-like patterns
Functional Components Learn about functional components
Component Composition Nest and compose components