Diffing Algorithm
O!‘s diffing algorithm is intentionally simple and inefficient.How It Falls Short
From the README:“Beware, diffing algorithm is very dumb and inefficient.”The algorithm (o.mjs:282-285):
- Position-based only: Matches virtual nodes to DOM nodes by array index
- No move operations: Can only create, update, or remove nodes
- Recreates nodes unnecessarily: If a node changes position, it’s destroyed and recreated
- No key-based reconciliation: The
kproperty only tracks component hooks, not DOM element reuse
Performance Impact
- Large lists that change frequently
- Reordering items
- Complex dynamic UIs
Hook Rules
O!‘s hooks follow the same rules as React, but violations may be harder to debug.Must Call in Same Order
Because hooks are stored in an array and accessed by index (see How It Works), you must call hooks in the same order every render.Can’t Use in Loops
No Error Boundaries
Unlike React, O! has no error boundary mechanism. If a component throws an error, it will bubble up and potentially crash your entire app.Template Syntax Restrictions
Thex template parser has several limitations due to its simplicity.
Double-Quoted Attributes Only
Attribute values must be double-quoted unless they’re placeholders:/^"([^"]*)" (o.mjs:108) to match quoted values.
One Top-Level Tag Only
The template must have exactly one root element:stack[0].c[0] - the first child of the fake root node (o.mjs:127).
Limited Placeholder Positions
Placeholders can only appear in three places:- Tag names:
x`<${Component} />` - Attribute values:
x`<div className=${myClass} />` - Text content:
x`<div>${text}</div>`
No JSX Features
Unlike JSX, thex template syntax doesn’t support:
- Spread attributes:
<div {...props}> - Boolean attributes:
<input disabled />(must usedisabled="true") - Fragments:
<>...</> - Comments:
{/* comment */} - Multiline attribute values
- Self-closing HTML tags like
<br>(must use<br />)
Missing React Features
O! implements only a tiny subset of React’s functionality.No Additional Hooks
O! only provides:useStateuseReduceruseEffect
useContext- No context APIuseRef- No refsuseMemo/useCallback- No memoizationuseLayoutEffect- OnlyuseEffect- Custom hooks (you can write them, but limited by available hooks)
No Class Components
O! only supports functional components:No Synthetic Events
Event handlers receive native browser events, not React’s synthetic events:- No event pooling
- No automatic event normalization across browsers
- Case-sensitive event names (
onclick, notonClick)
No Portals
You cannot render components into different DOM trees.No Suspense or Lazy Loading
No built-in support for code splitting or lazy component loading.No DevTools
No browser extension for debugging components, inspecting state, or profiling.No Server-Side Rendering
O! can only render in the browser. NorenderToString or SSR support.
Property Handling Quirks
O! sets properties directly on DOM nodes rather than using attributes (except for SVG):- Use
classNamenotclass - Use
htmlFornotfor stylemust be a string, not an object:style="color: red;"notstyle={{ color: 'red' }}- Some HTML attributes may not work as expected
Event Handlers Are Lowercase
When to Use O!
Given these limitations, O! is best suited for: ✅ Learning: Understanding how React-like libraries work✅ Prototyping: Quick experiments and demos
✅ Tiny projects: Small single-page apps with simple UIs
✅ Teaching: Explaining virtual DOM and hooks concepts ❌ Not for:
- Production applications
- Large-scale projects
- Apps requiring high performance
- Projects with complex state management needs
- Anything user-facing that requires reliability
Next Steps
- Compare O! to React to understand the differences
- Read the author’s blog post about why O! was created
- Check out How It Works to understand the internals