Introduction: Signals

Signals

Signals are reactive containers that hold values and notify subscribers when changed.

Creating Signals

import { createSignal } from '@luna_ui/luna';

// Basic signal
const [count, setCount] = createSignal(0);

// With initial value
const [name, setName] = createSignal("Luna");

// With complex types
const [user, setUser] = createSignal({ name: "Alice", age: 25 });

Reading Values

Call the signal as a function to read its value:

const [count, setCount] = createSignal(5);

console.log(count());  // 5

// In JSX - creates reactive binding
<p>Count: {count()}</p>

Writing Values

Direct Set

const [count, setCount] = createSignal(0);

setCount(5);        // Set to 5
setCount(10);       // Set to 10

Functional Update

Update based on the previous value:

const [count, setCount] = createSignal(0);

setCount(c => c + 1);  // Increment
setCount(c => c * 2);  // Double

Peek (Read Without Tracking)

Read a signal without creating a dependency:

import { createSignal, createEffect } from '@luna_ui/luna';

const [count, setCount] = createSignal(0);
const [other, setOther] = createSignal(0);

createEffect(() => {
  // This effect only re-runs when `other` changes
  // even though we're reading `count`
  console.log(count.peek(), other());
});

Signals with Objects

When working with objects, you need to create a new object to trigger updates:

const [user, setUser] = createSignal({ name: "Alice", age: 25 });

// Wrong - mutating doesn't trigger update
user().age = 26;

// Correct - create new object
setUser(u => ({ ...u, age: 26 }));

Multiple Signals

Signals are independent. Changing one doesn't affect others:

const [firstName, setFirstName] = createSignal("John");
const [lastName, setLastName] = createSignal("Doe");

// Each updates independently
<p>First: {firstName()}</p>    {/* Updates when firstName changes */}
<p>Last: {lastName()}</p>      {/* Updates when lastName changes */}

Try It

Create a form with two inputs (first name, last name) and display the full name:

Solution
function NameForm() {
  const [firstName, setFirstName] = createSignal("");
  const [lastName, setLastName] = createSignal("");

  return (
    <div>
      <input
        value={firstName()}
        onInput={(e) => setFirstName(e.target.value)}
        placeholder="First name"
      />
      <input
        value={lastName()}
        onInput={(e) => setLastName(e.target.value)}
        placeholder="Last name"
      />
      <p>Full name: {firstName()} {lastName()}</p>
    </div>
  );
}

Next

Learn about Effects โ†’