A universal React-compatible render engine for building applications across multiple platforms
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Class-based component system providing React-compatible component lifecycle management and state handling. Rax supports both regular components and pure components with automatic shallow comparison optimization.
Base class for all Rax class components. Provides core component functionality including state management and lifecycle methods.
/**
* Base component class for creating stateful class components
*/
class Component {
/**
* Creates a new component instance
* @param props - Component properties passed from parent
* @param context - Component context for accessing shared data
*/
constructor(props, context);
/**
* Updates component state and triggers re-render
* @param partialState - Object containing state changes or function returning state changes
* @param callback - Optional callback executed after state update
*/
setState(partialState, callback);
/**
* Forces component to re-render regardless of state or props changes
* @param callback - Optional callback executed after re-render
*/
forceUpdate(callback);
// Instance properties
props: Object; // Component properties
context: Object; // Component context
refs: Object; // Deprecated ref collection
updater: Object; // Internal updater instance
}Usage Examples:
import { createElement, Component } from 'rax';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: props.initialCount || 0
};
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
incrementAsync = () => {
this.setState(
(prevState) => ({ count: prevState.count + 1 }),
() => {
console.log('State updated:', this.state.count);
}
);
}
render() {
return createElement('div', null,
createElement('p', null, `Count: ${this.state.count}`),
createElement('button', { onClick: this.increment }, 'Increment'),
createElement('button', { onClick: this.incrementAsync }, 'Increment Async')
);
}
}
// Usage
const counter = createElement(Counter, { initialCount: 5 });Optimized component class that automatically implements shallow comparison for props and state. Only re-renders when shallow comparison detects changes.
/**
* Pure component class with automatic shallow comparison optimization
* Extends Component and adds shallow comparison for props and state
*/
class PureComponent extends Component {
/**
* Creates a new pure component instance
* @param props - Component properties passed from parent
* @param context - Component context for accessing shared data
*/
constructor(props, context);
// Inherits all Component methods
// Automatically implements shouldComponentUpdate with shallow comparison
__isPureComponent: true; // Internal flag for pure component identification
}Usage Examples:
import { createElement, PureComponent } from 'rax';
class UserCard extends PureComponent {
render() {
const { user, theme } = this.props;
console.log('UserCard rendered'); // Only logs when props actually change
return createElement('div', {
className: `user-card ${theme}`
},
createElement('h3', null, user.name),
createElement('p', null, user.email),
createElement('span', null, `ID: ${user.id}`)
);
}
}
class UserList extends Component {
constructor(props) {
super(props);
this.state = {
theme: 'light',
users: [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
]
};
}
toggleTheme = () => {
this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' });
}
render() {
return createElement('div', null,
createElement('button', { onClick: this.toggleTheme },
`Switch to ${this.state.theme === 'light' ? 'dark' : 'light'} theme`
),
...this.state.users.map(user =>
createElement(UserCard, {
key: user.id,
user: user,
theme: this.state.theme
})
)
);
}
}Class components support React-compatible lifecycle methods. These are called automatically by the Rax runtime during component mounting, updating, and unmounting.
Mounting Lifecycle:
constructor(props, context)componentDidMount()Updating Lifecycle:
componentDidUpdate(prevProps, prevState, snapshot)shouldComponentUpdate(nextProps, nextState) (only for regular Component, not PureComponent)Unmounting Lifecycle:
componentWillUnmount()Error Handling:
componentDidCatch(error, errorInfo)/**
* Component lifecycle methods (optional implementations)
*/
interface ComponentLifecycle {
/**
* Called immediately after component is mounted to DOM
*/
componentDidMount?(): void;
/**
* Called immediately after component updates
* @param prevProps - Previous props before update
* @param prevState - Previous state before update
* @param snapshot - Value returned from getSnapshotBeforeUpdate
*/
componentDidUpdate?(prevProps: Object, prevState: Object, snapshot?: any): void;
/**
* Called immediately before component is unmounted and destroyed
*/
componentWillUnmount?(): void;
/**
* Determines if component should re-render (Component only, not PureComponent)
* @param nextProps - Next props that will be received
* @param nextState - Next state that will be set
* @returns true if component should update, false otherwise
*/
shouldComponentUpdate?(nextProps: Object, nextState: Object): boolean;
/**
* Called when an error occurs in any child component
* @param error - The error that was thrown
* @param errorInfo - Information about the error
*/
componentDidCatch?(error: Error, errorInfo: Object): void;
}Lifecycle Usage Example:
import { createElement, Component } from 'rax';
class DataFetcher extends Component {
constructor(props) {
super(props);
this.state = {
data: null,
loading: true,
error: null
};
}
async componentDidMount() {
try {
const response = await fetch(this.props.url);
const data = await response.json();
this.setState({ data, loading: false });
} catch (error) {
this.setState({ error: error.message, loading: false });
}
}
componentDidUpdate(prevProps) {
if (prevProps.url !== this.props.url) {
this.setState({ loading: true });
this.fetchData();
}
}
componentWillUnmount() {
// Cleanup any subscriptions or timers
if (this.timer) {
clearInterval(this.timer);
}
}
componentDidCatch(error, errorInfo) {
console.error('DataFetcher caught an error:', error, errorInfo);
this.setState({ error: 'Something went wrong' });
}
render() {
const { data, loading, error } = this.state;
if (loading) {
return createElement('div', null, 'Loading...');
}
if (error) {
return createElement('div', null, `Error: ${error}`);
}
return createElement('div', null,
createElement('pre', null, JSON.stringify(data, null, 2))
);
}
}// Component constructor type
interface ComponentConstructor {
new (props: Object, context?: Object): Component;
}
// Component instance interface
interface ComponentInstance {
props: Object;
context: Object;
state: Object;
refs: Object;
updater: Object;
setState(partialState: Object | Function, callback?: Function): void;
forceUpdate(callback?: Function): void;
}
// State updater function type
type StateUpdater<S> = (prevState: S, props: Object) => Partial<S>;
// setState parameter types
type SetStateParameter<S> = Partial<S> | StateUpdater<S>;
// Component lifecycle method types
type ComponentDidMountMethod = () => void;
type ComponentDidUpdateMethod = (prevProps: Object, prevState: Object, snapshot?: any) => void;
type ComponentWillUnmountMethod = () => void;
type ShouldComponentUpdateMethod = (nextProps: Object, nextState: Object) => boolean;
type ComponentDidCatchMethod = (error: Error, errorInfo: Object) => void;Install with Tessl CLI
npx tessl i tessl/npm-rax