---
title: Reactivity | Concepts
contributors:
  - wmertens
  - bado22
  - RATIU5
  - manucorporat
  - adamdbradley
  - fleish80
  - saikatdas0790
  - dario-piotrowicz
  - the-r3aper7
  - AnthonyPAlicea
  - mhevery
  - wtlin1228
  - mrhoodz
  - thejackshelton
  - aivarsliepa
  - zanettin
updated_at: '2023-09-05T18:38:51Z'
created_at: '2023-03-20T23:45:13Z'
---

# Reactivity

Reactivity allows Qwik to track which components are subscribed to which state. This information enables Qwik to invalidate only the relevant component on state change, which minimizes the number of components that need to be re-rendered.

Without fine-grained reactivity, a state change would require re-rendering from the root component, which would force the whole component tree to be eagerly downloaded.

It's important to notice that Qwik does not do change detection like Angular. Instead, Qwik relies on signals to surgically update the component templates when the relevant state changes, without having to dirty-check the whole state.

## Proxy

Reactivity requires that the framework keeps track of the relationship between the state of the application and the components. The framework must render the whole application at least once to build the reactivity graph. The build of this reactivity graph initially happens on the server and is serialized to HTML so that the browser can use the information without being forced to do a single pass through all components to rebuild the graph. (Qwik does not need to do hydration to register events or build up the reactivity graph).

Reactivity can be done in a few ways:

1. Using explicit registration of listeners using `.subscribe()` (for example, RxJS)
2. Using implicit registration using a compiler (for example, Svelte)
3. Using implicit registration using proxies.

Qwik uses proxies for a few reasons:

1. Using explicit registration such as `.subscribe()` would require the system to serialize all of the subscribed listeners to avoid hydration. Serializing subscribed closures would not be possible, as all the subscribe functions would have to be lazy-loaded and asynchronous (too expensive).
2. Using the compiler to create graphs implicitly would work, but only for components. Intra component communications would still require `.subscribe()` methods and hence suffer the issues described above.

Because of the above constraints, Qwik uses proxies to keep track of the reactivity graph.

- Use [`useStore()`](/docs/(qwik)/components/state/index.mdx#usestore) to create a store proxy.
- The proxy notices the reads and creates subscriptions that are serializable.
- The proxy notices the writes and uses the subscription information to invalidate the relevant components.

## Counter Example

```tsx
export const Counter = component$(() => {
  const store = useStore({ count: 0 });

  return <button onClick$={() => store.count++}>{store.count}</button>;
});
```

1. The server performs an initial render of the component. The server rendering includes creating the proxy represented by `store`.
2. The initial render invokes the OnRender method, which has a reference to the `store` proxy. The rendering puts the proxy in "learn" mode. During the build-up of JSX, the proxy observes a read of the `count` property. Because the proxy is in "learn" mode, it records that the text node inside `Counter` has a subscription on the `store.count`.
3. The server serializes the state of the application into HTML. This includes the `store` as well as subscription information which says that the text node inside `Counter` is subscribed to `store.count`.
4. In the browser, the user clicks the button. Because the click event handler closed over `store`, Qwik restores the store proxy. The proxy contains the application state (the count) and the subscription, which associates the text node inside `Counter` with `state.count`.
5. The event handler increments the `store.count`. Because the `store` is a proxy, it notices the write and uses the subscription information to create a signal operation to update the text node inside `Counter`.
6. After `requestAnimationFrame`, the signal value is reflected in the DOM by updating the text node's value to that of the signal.

## Unsubscribe example

```tsx
export const ComplexCounter = component$(() => {
  const store = useStore({ count: 0, visible: true });

  return (
    <>
      <button onClick$={() => (store.visible = !store.visible)}>
        {store.visible ? 'hide' : 'show'}
      </button>
      <button onClick$={() => store.count++}>increment</button>
      {store.visible ? <p>{store.count}</p> : null}
    </>
  );
});
```

This example is a more complicated counter.

- It contains the `increment` button, which always increments `store.count`.
- It contains a `show`/`hide` button which determines if the count is shown.

1. On the initial render, the count is visible. Therefore the server creates a subscription that records that `ComplexCounter` needs to get re-rendered if either `store.count` or `store.visible` changes.
2. If the user clicks on `hide`, the `ComplexCounter` rerenders. The re-rendering clears all of the subscriptions and records new ones. This time the JSX does not read `store.count`. Therefore, only `store.visible` gets added to the list of subscriptions.
3. User clicking on `increment` will update `store.count`, but doing so will not cause the component to re-render. This is correct because the counter is not visible, so re-rendering would be a no-op.
4. If the user clicks `show`, the component will re-render and this time the JSX will read both `store.visible` as well as `store.count`. The subscription list is once again updated.
5. Now, clicking on `increment` updates the `store.count`. Because the count is visible, the `ComplexCounter` is subscribed to `store.count`.

Notice how the set of subscriptions automatically updates as the component renders different branches of its JSX. The advantage of the proxy is that the subscriptions update automatically as the applications execute, and the system can always compute the smallest set of invalidated components.

## Deep objects

So far, the examples show the store (`useStore()`) was a simple object with primitive values.

```tsx
export const MyComp = component$(() => {
  const store = useStore({
    person: { first: null, last: null },
    location: null
  });

  store.location = {street: 'main st'};

  return (
    <section>
      <p>{store.person.last}, {store.person.first}</p>
      <p>{store.location.street}</p>
    </section>
  );
})
```

In the above examples, Qwik will automatically wrap child objects `person` and `location` into a proxy and correctly create subscriptions on all deep properties.

The wrapping behavior described above has one surprising side-effect. Writing and reading from a proxy auto wraps the object, which means that the identity of the object changes. This should normally not be an issue, but it is something that the developer should keep in mind.

```tsx
export const MyComp = component$(() => {
  const store = useStore({ person: null });
  const person = { first: 'John', last: 'Smith' };
  store.person = person; // store.person auto wraps object into proxy

  if (store.person !== person) {
    // The consequence of auto wrapping is that the object identity changes.
    console.log('store auto-wrapped person into a proxy');
  }
});
```

## Out-of-order rendering

Qwik components are rendered out of order. A component can be rendered without forcing a parent component to be rendered first or a child components to be rendered as a consequence of the component render. This is an important property of Qwik because it allows Qwik applications to only re-render components which have been invalidated due to a state change rather than re-rendering the whole component tree on a state change.

When components are rendered, they need to have access to their props. Parent components create props. The props must be [serializable](../resumable/index.mdx#serialization) for the component to render independently from the parent.

## Invalidating child components

When re-rendering a component, the child component's props either stay the same or are updated. A child component only invalidates if its props change.

```tsx
export const Child = component$((props: { count: number }) => {
  return <span>{props.count}</span>;
});

export const MyApp = component$(() => {
  const store = useStore({ a: 0, b: 0, c: 0 });

  return (
    <>
      <button onClick$={() => store.a++}>a++</button>
      <button onClick$={() => store.b++}>b++</button>
      <button onClick$={() => store.c++}>c++</button>
      {JSON.stringify(store)}

      <Child count={store.a} />
      <Child count={store.b} />
    </>
  );
});
```

In the above example, there are two `<Child/>` components.

- Every time a button is clicked, one of the three counters is incremented. A change of counter state will cause the `MyApp` component to re-render on each click.
- If `store.c` has been incremented, none of the child components get re-rendered. (And therefore, their code does not get lazy-loaded)
- If `store.a` has been incremented, then only `<Child count={store.a}/>` will re-render.
- If `store.b` has been incremented, then only `<Child count={store.b}/>` will re-render.

Notice that the child components only re-render when their props change. This is an important property of Qwik applications as it significantly limits the amount of re-rendering the application must do on some state change. While less re-rendering has performance benefits, the real benefit is that large portions of the applications do not get downloaded if they don't need to be re-rendered.
