Skip to content

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:

tsx
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:

tsx
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:

tsx
// ✅ 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:

PropertyReactivityUse CaseValue TypesExample
.value❌ NoOne-time reads, event handlersAll typesconst current = sCount.value;
.use()✅ YesComplex rendering, objectsAll typesconst user = sUser.use();
.html✅ YesSimple primitive displaysString, 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)
tsx
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
tsx
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

tsx
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

tsx
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

tsx
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:

tsx
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

  1. Use for simple displays: Perfect for titles, counters, labels
  2. Avoid over-usage: Don't use for every primitive value
  3. Consider alternatives: Sometimes .use() with formatting is better
tsx
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):

tsx
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

tsx
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

tsx
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

tsx
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:

tsx
// ✅ 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

Released under the MIT License.