Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Signals

A signal is a reactive value: when it changes, Solid updates every place on the page where it was read. Signals hold everything that changes over time: counters, the text in an input, whether a menu is open.

Creating a signal

The createSignal function from the solid-js package takes an initial value and returns a pair: a getter and a setter.

// src/components/Counter.jsx
import { createSignal } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
 
  return (
    <div>
      <p>Tasks done: {count()}</p>
      <button onClick={() => setCount(count() + 1)}>Mark done</button>
    </div>
  );
}

Render the component in src/App.jsx with <Counter /> after the import import Counter from './components/Counter';. Each click on the button increases the number in the paragraph by one.

The getter is a function

ActionCode
Read the valuecount()
Write a new valuesetCount(5)
Change based on the current valuesetCount((c) => c + 1)

Reading by calling is the main difference from useState in React. Calling count() inside JSX tells Solid that this piece of markup depends on the signal. When the signal changes, Solid updates only the text node with the number, without touching the rest of the markup and without calling Counter again.

A signal with a string

A signal can hold a value of any type:

// src/components/Greeting.jsx
import { createSignal } from 'solid-js';
 
export default function Greeting() {
  const [name, setName] = createSignal('Anna');
 
  return (
    <div>
      <p>Hello, {name()}!</p>
      <button onClick={() => setName('Oleg')}>Change name</button>
    </div>
  );
}

After the click the text changes to "Hello, Oleg!".

A signal outside a component

A signal is not tied to a component. You can create it in a separate file and import it in several places — they all see the same value:

// src/state/counter.js
import { createSignal } from 'solid-js';
 
export const [done, setDone] = createSignal(0);

Any component that calls done() in its markup updates after setDone(...). For small apps this is often enough instead of context.

Objects and arrays

The setter compares the new value with the old one using ===. If you pass the same array changed with push, nothing updates. Create a new array: setTodos([...todos(), item]). For complex lists stores are more convenient — they have their own lesson.

Common mistake

Saving a signal's value in a variable and rendering that:

// src/components/Counter.jsx
import { createSignal } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
  const value = count(); // read only once
 
  return <button onClick={() => setCount(count() + 1)}>{value}</button>;
}

The button shows 0 forever: the component ran once, and value is never recalculated. Read the signal right in JSX — {count()}.

Thanks for reading!

Donate to the site — we work hard for you.