Provides a compatibility with React codebases
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Lower-level VNode creation and manipulation functions for advanced use cases, providing direct access to Inferno's virtual DOM internals while maintaining React compatibility.
Creates virtual DOM nodes with explicit flags and properties for maximum control.
/**
* Creates a virtual DOM node with explicit configuration
* @param flags - VNode flags defining element type and behavior
* @param type - Element type (string for DOM, function/class for components)
* @param className - CSS class name for the element
* @param children - Child nodes
* @param childFlags - Flags describing children structure
* @param props - Element properties and attributes
* @param key - Unique key for reconciliation
* @param ref - Reference to DOM element or component instance
* @returns VNode representing the virtual DOM element
*/
function createVNode(
flags: number,
type: string | ComponentClass<any> | Function | null,
className?: string,
children?: InfernoNode,
childFlags?: number,
props?: any,
key?: string | number,
ref?: any
): VNode;Usage Examples:
import { createVNode, VNodeFlags } from "inferno-compat";
// Create a simple element VNode
const div = createVNode(
VNodeFlags.HtmlElement,
'div',
'container',
'Hello World',
VNodeFlags.HasNonKeyedChildren,
{ id: 'main' },
'unique-key'
);
// Create a component VNode
function MyComponent(props) {
return createVNode(VNodeFlags.HtmlElement, 'span', null, props.text);
}
const component = createVNode(
VNodeFlags.ComponentFunction,
MyComponent,
null,
null,
VNodeFlags.HasNonKeyedChildren,
{ text: 'Component text' },
'component-key'
);
// Create VNode with ref
let elementRef;
const withRef = createVNode(
VNodeFlags.HtmlElement,
'input',
'form-input',
null,
VNodeFlags.HasNonKeyedChildren,
{ type: 'text', placeholder: 'Enter text' },
null,
(ref) => { elementRef = ref; }
);Creates VNodes specifically for React/Inferno components.
/**
* Creates a VNode for a component (class or function)
* @param flags - Component flags (ComponentClass or ComponentFunction)
* @param type - Component class or function
* @param props - Component props
* @param key - Unique key for reconciliation
* @param ref - Reference to component instance
* @returns VNode for the component
*/
function createComponentVNode(
flags: number,
type: ComponentClass<any> | Function,
props?: any,
key?: string | number,
ref?: any
): VNode;Usage Examples:
import { createComponentVNode, VNodeFlags, Component } from "inferno-compat";
class UserProfile extends Component {
render() {
return <div>User: {this.props.name}</div>;
}
}
// Create class component VNode
const classComponent = createComponentVNode(
VNodeFlags.ComponentClass,
UserProfile,
{ name: 'Alice', age: 30 },
'user-profile',
(instance) => console.log('Component mounted:', instance)
);
// Function component VNode
function WelcomeMessage({ message }) {
return <h1>{message}</h1>;
}
const functionComponent = createComponentVNode(
VNodeFlags.ComponentFunction,
WelcomeMessage,
{ message: 'Welcome to our app!' },
'welcome-message'
);
// Higher-order component pattern
function withLogging(WrappedComponent) {
function LoggingComponent(props) {
console.log('Rendering with props:', props);
return createComponentVNode(
VNodeFlags.ComponentFunction,
WrappedComponent,
props
);
}
return LoggingComponent;
}
const EnhancedComponent = withLogging(WelcomeMessage);
const enhanced = createComponentVNode(
VNodeFlags.ComponentFunction,
EnhancedComponent,
{ message: 'Enhanced message' }
);Creates text nodes for efficient text rendering.
/**
* Creates a text VNode for rendering text content
* @param text - Text content to render
* @param key - Optional key for reconciliation
* @returns VNode representing text content
*/
function createTextVNode(text: string | number, key?: string | number): VNode;Usage Examples:
import { createTextVNode, createVNode, VNodeFlags } from "inferno-compat";
// Simple text node
const greeting = createTextVNode('Hello World!');
// Text with key for lists
const listItems = ['Apple', 'Banana', 'Cherry'].map((fruit, index) =>
createVNode(
VNodeFlags.HtmlElement,
'li',
null,
createTextVNode(fruit, `fruit-${index}`),
VNodeFlags.HasNonKeyedChildren,
null,
`item-${index}`
)
);
// Dynamic text content
function DynamicText({ value, formatter }) {
const formattedValue = formatter ? formatter(value) : value;
return createTextVNode(formattedValue);
}
// Conditional text rendering
function StatusText({ status }) {
const text = status === 'loading'
? createTextVNode('Loading...', 'loading-text')
: createTextVNode(`Status: ${status}`, 'status-text');
return createVNode(
VNodeFlags.HtmlElement,
'span',
`status ${status}`,
text
);
}
// Number text nodes
const counter = createTextVNode(42);
const price = createTextVNode(19.99);Creates fragment nodes for grouping elements without DOM wrappers.
/**
* Creates a fragment VNode for grouping multiple elements
* @param children - Array of child VNodes
* @param childFlags - Flags describing children structure
* @param key - Optional key for reconciliation
* @returns Fragment VNode containing the children
*/
function createFragment(
children: InfernoNode[],
childFlags?: number,
key?: string | number
): VNode;Usage Examples:
import { createFragment, createVNode, createTextVNode, VNodeFlags } from "inferno-compat";
// Simple fragment
const fragment = createFragment([
createVNode(VNodeFlags.HtmlElement, 'h1', null, createTextVNode('Title')),
createVNode(VNodeFlags.HtmlElement, 'p', null, createTextVNode('Content'))
], VNodeFlags.HasNonKeyedChildren);
// Fragment in conditional rendering
function ConditionalContent({ showDetails, title, content }) {
if (!showDetails) {
return createTextVNode(title);
}
return createFragment([
createVNode(VNodeFlags.HtmlElement, 'h2', null, createTextVNode(title)),
createVNode(VNodeFlags.HtmlElement, 'p', null, createTextVNode(content)),
createVNode(VNodeFlags.HtmlElement, 'button', null, createTextVNode('Close'))
], VNodeFlags.HasNonKeyedChildren, 'details-fragment');
}
// Fragment for list items
function TableRow({ cells }) {
const cellVNodes = cells.map((cell, index) =>
createVNode(
VNodeFlags.HtmlElement,
'td',
null,
createTextVNode(cell),
VNodeFlags.HasNonKeyedChildren,
null,
`cell-${index}`
)
);
return createFragment(cellVNodes, VNodeFlags.HasKeyedChildren, 'table-row');
}
// Nested fragments
const nestedFragment = createFragment([
createTextVNode('Before nested'),
createFragment([
createVNode(VNodeFlags.HtmlElement, 'span', null, createTextVNode('Nested 1')),
createVNode(VNodeFlags.HtmlElement, 'span', null, createTextVNode('Nested 2'))
], VNodeFlags.HasNonKeyedChildren, 'inner-fragment'),
createTextVNode('After nested')
], VNodeFlags.HasNonKeyedChildren, 'outer-fragment');Creates portal nodes that render children into different DOM containers.
/**
* Creates a portal VNode that renders children into a different DOM container
* @param children - VNodes to render in the portal
* @param container - DOM element to render the portal into
* @returns Portal VNode that renders children elsewhere
*/
function createPortal(
children: InfernoNode,
container: Element
): VNode;Usage Examples:
import { createPortal, createVNode, createTextVNode, VNodeFlags, Component } from "inferno-compat";
// Modal component using portal
class Modal extends Component {
constructor(props) {
super(props);
this.modalRoot = document.getElementById('modal-root') || document.body;
}
render() {
const modal = createVNode(
VNodeFlags.HtmlElement,
'div',
'modal-backdrop',
createVNode(
VNodeFlags.HtmlElement,
'div',
'modal-content',
this.props.children
)
);
return createPortal(modal, this.modalRoot);
}
}
// Tooltip component
function Tooltip({ children, content, targetRef }) {
if (!targetRef.current) return null;
const tooltip = createVNode(
VNodeFlags.HtmlElement,
'div',
'tooltip',
createTextVNode(content)
);
return createPortal(tooltip, targetRef.current.parentElement);
}
// Notification system
class NotificationManager extends Component {
constructor(props) {
super(props);
this.state = { notifications: [] };
this.notificationContainer = document.getElementById('notifications');
}
addNotification = (message, type = 'info') => {
const notification = {
id: Date.now(),
message,
type
};
this.setState(prevState => ({
notifications: [...prevState.notifications, notification]
}));
}
render() {
const { notifications } = this.state;
if (notifications.length === 0) return null;
const notificationList = createVNode(
VNodeFlags.HtmlElement,
'div',
'notification-list',
notifications.map(notification =>
createVNode(
VNodeFlags.HtmlElement,
'div',
`notification ${notification.type}`,
createTextVNode(notification.message),
VNodeFlags.HasNonKeyedChildren,
null,
notification.id
)
)
);
return createPortal(notificationList, this.notificationContainer);
}
}Creates ref objects for accessing DOM elements and component instances.
/**
* Creates a ref object for accessing DOM elements or component instances
* @returns Ref object with current property
*/
function createRef<T = any>(): { current: T | null };Usage Examples:
import { createRef, createVNode, VNodeFlags, Component } from "inferno-compat";
class InputComponent extends Component {
constructor(props) {
super(props);
this.inputRef = createRef();
}
componentDidMount() {
// Focus the input after mounting
if (this.inputRef.current) {
this.inputRef.current.focus();
}
}
getValue = () => {
return this.inputRef.current ? this.inputRef.current.value : '';
}
render() {
return createVNode(
VNodeFlags.HtmlElement,
'input',
'form-input',
null,
VNodeFlags.HasNonKeyedChildren,
{
type: 'text',
placeholder: this.props.placeholder,
ref: this.inputRef
}
);
}
}
// Functional component with ref
function VideoPlayer({ src }) {
const videoRef = createRef();
const play = () => {
if (videoRef.current) {
videoRef.current.play();
}
};
const pause = () => {
if (videoRef.current) {
videoRef.current.pause();
}
};
return createFragment([
createVNode(
VNodeFlags.HtmlElement,
'video',
'video-player',
null,
VNodeFlags.HasNonKeyedChildren,
{ src, ref: videoRef }
),
createVNode(
VNodeFlags.HtmlElement,
'div',
'controls',
[
createVNode(
VNodeFlags.HtmlElement,
'button',
null,
createTextVNode('Play'),
VNodeFlags.HasNonKeyedChildren,
{ onClick: play }
),
createVNode(
VNodeFlags.HtmlElement,
'button',
null,
createTextVNode('Pause'),
VNodeFlags.HasNonKeyedChildren,
{ onClick: pause }
)
]
)
]);
}Creates components that forward refs to child elements.
/**
* Creates a component that forwards refs to child elements
* @param render - Render function that receives props and ref
* @returns Component that forwards refs
*/
function forwardRef<T, P = {}>(
render: (props: P, ref: { current: T | null }) => InfernoNode
): ComponentType<P & { ref?: { current: T | null } }>;Usage Examples:
import { forwardRef, createVNode, VNodeFlags, createRef } from "inferno-compat";
// Forward ref to DOM element
const FancyButton = forwardRef((props, ref) => {
return createVNode(
VNodeFlags.HtmlElement,
'button',
`fancy-button ${props.variant || 'primary'}`,
createTextVNode(props.children),
VNodeFlags.HasNonKeyedChildren,
{
...props,
ref: ref
}
);
});
// Usage with ref
function App() {
const buttonRef = createRef();
const handleClick = () => {
if (buttonRef.current) {
buttonRef.current.classList.add('clicked');
}
};
return createVNode(
VNodeFlags.ComponentFunction,
FancyButton,
null,
null,
VNodeFlags.HasNonKeyedChildren,
{
variant: 'secondary',
onClick: handleClick,
ref: buttonRef,
children: 'Click Me'
}
);
}
// Forward ref to child component
const EnhancedInput = forwardRef((props, ref) => {
return createVNode(
VNodeFlags.HtmlElement,
'div',
'input-wrapper',
[
props.label && createVNode(
VNodeFlags.HtmlElement,
'label',
'input-label',
createTextVNode(props.label)
),
createVNode(
VNodeFlags.HtmlElement,
'input',
'enhanced-input',
null,
VNodeFlags.HasNonKeyedChildren,
{
...props,
ref: ref
}
)
]
);
});Understanding VNode flags is crucial for advanced VNode manipulation:
enum VNodeFlags {
// Element types
HtmlElement = 1,
SvgElement = 2,
InputElement = 4,
TextareaElement = 8,
SelectElement = 16,
// Component types
ComponentFunction = 32,
ComponentClass = 64,
ComponentUnknown = 128,
// Children types
HasKeyedChildren = 256,
HasNonKeyedChildren = 512,
// Special flags
Fragment = 1024,
Portal = 2048,
ReCreate = 4096,
ContentEditable = 8192,
UpdateEffect = 16384,
Ref = 32768
}These functions enable advanced patterns like: