Coming from React

You write SolidRT apps with SolidJS 2. If you know React, the JSX looks the same. But the time when code runs is different. This page gives a short comparison. The SolidJS docs give a full description of the model.

The primary difference

A React component runs again at each state change, and React compares the result with the previous result. A Solid component runs one time, to set up the app. When JSX reads a signal, that one location in the JSX connects to the signal. An update changes only that location. Solid does not render again and does not use a virtual DOM.

function Counter() {
  let [count, setCount] = createSignal(0)
  console.log("runs once")
  return (
    <view onPointerDown={() => setCount(count() + 1)}>
      <text>Tapped {count()} times</text>
    </view>
  )
}

Most of the differences in the table below come from this difference.

Comparison table

React SolidJS 2
useState createSignal. To read it, call it: count()
useMemo createMemo
useReducer, nested state createStore. Update it through a draft: setStore(s => { s.done = true })
useEffect createEffect(compute, apply). compute tracks, and apply does the side effect
useEffect(..., []) for mount and cleanup onSettled(() => { ...; return cleanup })
useRef for a value that stays between renders A usual let in the component body. The body runs only one time
useRef for an element ref={el => (box = el)}
useCallback A usual function. The body runs only one time
useContext, <Ctx.Provider value> useContext. The context is also its provider: <Ctx value>
Destructured props: ({ title }) => (props) =>. Read props.title where you use it
{cond && <X />} <Show when={cond()}><X /></Show>
items.map(...) with key <For each={items()}>. It uses identity as the key. For a different key, use keyed={item => item.id}
<Suspense> <Loading>
Error boundaries <Errored>
Rules of hooks No rules about where to make signals. Make them in any sequence, also in conditions

Three usual errors

Do not destructure props. Props are reactive values. Each time you read props.title, you get the current value. let { title } = props reads the value only one time. Then the component does not see updates.

Give values, not signals. Write <Counter value={count()} />, not value={count}. The JSX gives the call to the child reactively. The child reads a usual value from props.value.

Do not read a signal at the top of the component body. The body runs one time, so the read gets only the first value. Read the signal in the JSX, or in createMemo.

In SolidRT

Import all names from @solidrt/core, not from solid-js. @solidrt/core exports the reactive and control-flow names again, together with the elements and the remaining parts of Core. The elements are native nodes, not DOM elements. Thus, there is no className, style or onClick. The element vocabulary shows what to use.