The .html
Property: Simple Reactive Rendering
Overview
The .html
property in React Signify provides a convenient way to render primitive values (strings and numbers) directly in your JSX. It's a reactive property that automatically updates when your state changes, making it perfect for simple displays.
What Makes .html
Special?
Unlike other properties in React Signify, .html
combines the reactive benefits of .use()
with the simplicity of direct rendering. Here's what makes it unique:
- ✅ Reactive: Automatically updates when state changes
- ✅ Simple: No need for additional JSX wrapping
- ✅ Type-safe: Only available for primitive values
- ✅ Convenient: Perfect for simple text/number displays
Step-by-Step Guide
Step 1: Basic Usage with Strings
Let's start with the simplest example - rendering a string value:
import { signify } from 'react-signify';
// Create a string state
const sMessage = signify('Hello World');
function BasicExample() {
return (
<div>
<h1>{sMessage.html}</h1>
</div>
);
}
What happens here:
sMessage.html
creates a reactive component- The component subscribes to
sMessage
changes - When
sMessage
updates, the<h1>
automatically re-renders
Step 2: Working with Numbers
Numbers work just as seamlessly:
const sCount = signify(0);
const sPrice = signify(29.99);
function NumberExample() {
return (
<div>
<p>Items: {sCount.html}</p>
<p>Price: ${sPrice.html}</p>
<button onClick={() => sCount.set(prev => prev + 1)}>
Add Item
</button>
</div>
);
}
Key points:
- Numbers render directly without conversion
- Changes trigger automatic re-renders
- Perfect for counters, prices, scores, etc.
Step 3: Understanding Type Restrictions
The .html
property is only available for primitive values. This is enforced by TypeScript:
// ✅ These work - primitive values
const sTitle = signify('Welcome'); // string
const sCount = signify(42); // number
// ❌ These don't have .html - non-primitive values
const sUser = signify({ name: 'John' }); // object
const sItems = signify(['a', 'b', 'c']); // array
const sActive = signify(true); // boolean
function TypeExample() {
return (
<div>
{/* ✅ Works */}
<h1>{sTitle.html}</h1>
<p>Count: {sCount.html}</p>
{/* ❌ TypeScript errors - .html not available */}
{/* <div>{sUser.html}</div> */}
{/* <div>{sItems.html}</div> */}
{/* <div>{sActive.html}</div> */}
{/* ✅ Use .use() for non-primitives */}
<div>User: {sUser.use().name}</div>
<div>Active: {sActive.use() ? 'Yes' : 'No'}</div>
</div>
);
}
Comparing .html
with Other Properties
Understanding when to use .html
vs other properties is crucial:
Property | Reactivity | Use Case | Value Types | Example |
---|---|---|---|---|
.value | ❌ No | One-time reads, event handlers | All types | const current = sCount.value; |
.use() | ✅ Yes | Complex rendering, objects | All types | const user = sUser.use(); |
.html | ✅ Yes | Simple primitive displays | String, Number | <h1>{sTitle.html}</h1> |
When to Use .html
Use .html
when you have:
- Simple string or number values
- Direct display needs (no complex formatting)
- Reactive requirements (auto-updates)
const sUserName = signify('Alice');
const sScore = signify(95);
function GoodUseCase() {
return (
<div>
{/* ✅ Perfect for .html */}
<h2>Welcome, {sUserName.html}!</h2>
<p>Score: {sScore.html}</p>
</div>
);
}
When NOT to Use .html
Avoid .html
when you need:
- Complex formatting
- Object/array rendering
- Conditional logic
const sUser = signify({ name: 'Alice', score: 95 });
function AvoidHtml() {
const user = sUser.use(); // ✅ Use .use() for objects
return (
<div>
{/* ✅ Complex formatting - use .use() */}
<h2>Welcome, {user.name.toUpperCase()}!</h2>
{/* ✅ Conditional logic - use .use() */}
<p>Grade: {user.score >= 90 ? 'A' : 'B'}</p>
</div>
);
}
Real-World Examples
Example 1: Live Counter
const sCounter = signify(0);
function LiveCounter() {
const increment = () => sCounter.set(prev => prev + 1);
const decrement = () => sCounter.set(prev => prev - 1);
const reset = () => sCounter.set(0);
return (
<div>
<h1>Count: {sCounter.html}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
Example 2: Dynamic Title
const sPageTitle = signify('Home');
function DynamicNavigation() {
const pages = ['Home', 'About', 'Contact', 'Blog'];
return (
<div>
<h1>{sPageTitle.html}</h1>
<nav>
{pages.map(page => (
<button
key={page}
onClick={() => sPageTitle.set(page)}
>
{page}
</button>
))}
</nav>
</div>
);
}
Example 3: Live Status Display
const sConnectionStatus = signify('Connected');
const sUserCount = signify(1337);
function StatusBar() {
return (
<div style={{
padding: '10px',
background: '#f0f0f0',
display: 'flex',
justifyContent: 'space-between'
}}>
<span>Status: {sConnectionStatus.html}</span>
<span>Users Online: {sUserCount.html}</span>
</div>
);
}
Performance Considerations
Reactivity Cost
The .html
property creates reactive subscriptions, which means:
const sMessage = signify('Hello');
function PerformanceExample() {
// ✅ Reactive - component re-renders when sMessage changes
return <h1>{sMessage.html}</h1>;
// vs
// ❌ Static - no re-render, but no updates either
// return <h1>{sMessage.value}</h1>;
}
Best Practices
- Use for simple displays: Perfect for titles, counters, labels
- Avoid over-usage: Don't use for every primitive value
- Consider alternatives: Sometimes
.use()
with formatting is better
const sPrice = signify(29.99);
function PriceDisplay() {
// ✅ Simple display
return <span>{sPrice.html}</span>;
// ✅ Complex formatting - use .use()
const price = sPrice.use();
return <span>{price.toFixed(2)} USD</span>;
}
Integration with Sliced State
The .html
property is also available on sliced state (when the slice returns a primitive):
const sUser = signify({
name: 'Alice',
score: 95
});
// Create slices that return primitives
const ssUserName = sUser.slice(user => user.name); // string slice
const ssUserScore = sUser.slice(user => user.score); // number slice
function SliceExample() {
return (
<div>
{/* ✅ Available because slices return primitives */}
<h2>{ssUserName.html}</h2>
<p>Score: {ssUserScore.html}</p>
</div>
);
}
Common Mistakes and Solutions
Mistake 1: Using with Objects
const sUser = signify({ name: 'Alice' });
// ❌ Won't work - objects don't have .html
// return <div>{sUser.html}</div>;
// ✅ Correct approach
return <div>{sUser.use().name}</div>;
Mistake 2: Complex Formatting
const sPrice = signify(29.99);
// ❌ Can't format with .html
// return <span>{sPrice.html.toFixed(2)}</span>;
// ✅ Use .use() for formatting
const price = sPrice.use();
return <span>{price.toFixed(2)}</span>;
Mistake 3: Conditional Rendering
const sCount = signify(0);
// ❌ Can't use conditions directly with .html
// return <div>{sCount.html > 0 && 'Items available'}</div>;
// ✅ Use .use() for conditions
const count = sCount.use();
return <div>{count > 0 && 'Items available'}</div>;
Summary
The .html
property is a powerful feature for rendering primitive values reactively in React Signify:
- Purpose: Simple, reactive rendering of strings and numbers
- Benefits: Automatic updates, type safety, clean syntax
- Limitations: Only primitives, no complex formatting
- Best for: Titles, counters, labels, simple displays
Use .html
when you need reactive primitive displays, and .use()
when you need more control or work with complex data types.
Quick Reference:
// ✅ Perfect use cases
<h1>{sTitle.html}</h1> // String display
<span>{sCount.html}</span> // Number display
// ✅ Alternative approaches
<h1>{sTitle.use()}</h1> // Same result with .use()
<span>{sCount.use()}</span> // Same result with .use()
// ✅ When you need more control
<h1>{sTitle.use().toUpperCase()}</h1> // String formatting
<span>${sPrice.use().toFixed(2)}</span> // Number formatting