How to use RxJS in Qwik
Tags: qwik, rxjs
Published: 2022-10-24 08:56:39

---
title: How to use RxJS in Qwik
published: true
description: How to lazy-load RxJS pipelines in Qwik
tags: qwik,rxjs
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wz0v1laduws8q4kwlrmi.png
series: RxJS and Qwik
# Use a ratio of 100:42 for best results.
---

[YouTube video for this article](https://www.youtube.com/watch?v=DA8lOSGtwgY)

RxJS isn't supported in Qwik, but [if we want to code reactively in Qwik today, we need RxJS](https://dev.to/mfp22/why-rxjs-compatibility-matters-gl2).

So how can we use RxJS on top of Qwik in a way that follows Qwik's philosophy of optimizing every bit of code to be downloaded to the client as late as possible?

RxJS's subscription model fits well with Qwik's philosophy of fine-grained code splitting: RxJS streams do nothing until something subscribes, so why perform work—or load the code to do that work—if nobody is listening?

But since we can't serialize RxJS directly, when the app renders on the server it should pass subscription information all the way up the RxJS chain, storing it in Qwik stores. Then when it loads on the client, we can check if an event has subscribers before loading any of the RxJS to process it. 

We can also defer loading downstream RxJS until new values get there. So if we have a typeahead with a `BehaviorSubject`, a `debounceTime` and a `switchMap`, we won't need to load the code for the `BehaviorSubject` or `debounceTime` until the user types, or for the `switchMap` until a value gets past the `filter`. This is how Qwik would behave if we implemented it without RxJS, only using Qwik stores and `useWatch$`s.

This is the ideal behavior.

![That'd be great](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2cmkl4471yig7hinuoh.png)

Unfortunately, after descending into a fairly deep rabbit hole, I still had no implementation that could work for all situations. This is an open challenge still. I will include my notes at the end of this article for anyone who wants to follow after me. This definitely is worth an NPM package once solved, and right now I want to focus on [StateAdapt](https://state-adapt.github.io/), so I won't be investing anymore time on this for now. 

**However, there is still a way to use RxJS in Qwik. And it's pretty good I think.**

## The solution that works now

![Server sad client happy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6smgxezep8gd7y5vtgze.png)

Since we don't know how to serialize RxJS yet, we need to set up RxJS from scratch on the client. We can't break up the streams and load each segment lazily, but we can at least wait until RxJS somewhere on the stream is required before loading the whole stream. That's still better than what other frameworks could do without a lot of work or inconvenient syntax, so we shouldn't be too sad. 

Sometimes we'll need a `useClientEffect$` to get some immediate RxJS behavior, but the ideal API should make it easy to switch between that and the lazy `useWatch$` hook, and we should prefer `useWatch$` where possible. 

Whenever we define an observable, we need to define the observables it depends on. We also need all the observables that depend on it, so we can find out if there is a subscription at the bottom. This way we'll have the expected/usual, lazy RxJS behavior of no unnecessary work being done until something subscribes. **This means once one observable is needed, the entire reactive graph of observables that contains that observable needs to be loaded.**

The way to trigger code to load in Qwik is to set state inside a Qwik store and use a hook to react to that state change. So every observable needs a corresponding store and `useWatch$` that reacts to the store by loading and running the code that defines the observable. When one observable is loaded, we need a chain reaction that causes all observable code in the graph to load, and then for the observables to be defined from top to bottom. 

So, to determine the exact architecture of this system, let's look at the different situations that might first trigger some RxJS behavior.

## Example 1: User input

Imagine a typeahead that uses this RxJS:

```tsx
const search$ = new BehaviorSubject('');

const results$ = search$.pipe(
  debounceTime(500),
  filter((search) => !!search.length),
  distinctUntilChanged(),
  switchMap((search) => fetchItems(search)),
);
```

Qwik stores can hold state just like a `BehaviorSubject`, so we don't need to define the `BehaviorSubject` until the user types. 

When the user types, we can set a Qwik store's `value` property and track it inside a `useWatch$`. Inside the `useWatch$` we can define the `BehaviorSubject`. 

Immediately after the `BehaviorSubject` is defined, we need to define the `results$` observable. We need a generic hook that can react to any parent observable being defined. So we need to assign the parent observable to a Qwik store property that can be tracked. But how can we do this if observables can't be serialized? Well, it turns out that Qwik stores can contain unserializable values if you pass them through Qwik's `noSerialize` function first.

So, when the user types, let's have a property that we can define like 

```tsx
store.rx = noSerialize(new BehaviorSubject(initialValue));
```

Now we can have all the downstream RxJS load because it's tracking the `rx` properties of its dependency observable stores.

Here's what this looks like:

![RxJS in Qwik Demo 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nebda13zsw1hxb1xh2j1.gif)

Each box represents a Qwik store. When it turns blue, its `rx` property has been defined. I added a delay of 2000 ms to this so you can see how it propagates down the chain of RxJS Qwik stores. 

Here's the syntax for making this happen:

```tsx
export default component$(() => {
  console.log("rerendering");
  const searchA = useSubject("searchA");

  const results = useStream$(
    () =>
      rx(searchA).pipe(
        debounceTime(500),
        filter((search) => !!search.length),
        distinctUntilChanged(),
        switchMap(search => fetchItems(search))
      ),
    [[] as Result[], [searchA]]
  );

  const resultsOut = useSubscribe(results);

  return (
    <>
      {* ... *}
    </>
  );
});
```

There's a lot to explain here, so let's go through it and the source code for making it happen.

### `useSubject`

`useSubject` is our custom hook that defines the `BehaviorSubject` store. Before we look at that source code, here are some simple utilities it uses:

`RxStore` is the shape of the Qwik stores we're creating for RxJS:

```tsx
// utils/rx-store.type.ts
import { NoSerialize } from "@builder.io/qwik";
import { BehaviorSubject, Observable } from "rxjs";

export interface RxStore<T> {
  value: T;
  rx: NoSerialize<BehaviorSubject<T> | Observable<T>>;
  activated: boolean;
}
```

`propagationDelay` is a constant I'm using in a few files, so I created a dedicated file for it, but you can ignore it and remove the `setTimeout` around it whenever you see it.

`createRx` is a simple utility function I made for ensuring that a `BehaviorSubject` is defined on the `rx` property of an `RxStore`. It might be a terrible name. But here it is:

```tsx
import { noSerialize } from "@builder.io/qwik";
import { BehaviorSubject } from "rxjs";
import { RxStore } from "./rx-store.type";

export function createRx<T>(store: RxStore<T>, value: T) {
  return noSerialize(store.rx || new BehaviorSubject<T>(value));
}
```

Now we're ready for `useSubject`:

```tsx
// utils/use-subject.function.ts
import { useStore, useWatch$ } from "@builder.io/qwik";
import { BehaviorSubject } from "rxjs";
import { createRx } from "./create-rx.function";
import { propagationDelay } from "./propagation-delay.const";
import { RxStore } from "./rx-store.type";

export function useSubject<T>(initialState: T): RxStore<T> {
  const store: RxStore<T> = useStore({
    rx: undefined,
    value: initialState,
    activated: false,
  });

  useWatch$(({ track }) => {
    const value = track(store, "value");
    if (value !== initialState) {
      store.activated = true;

      if (store.rx) {
        (store.rx as BehaviorSubject<T>).next(value);
      } else {
        store.rx = createRx(store, value);
      }
    }
  });

  useWatch$(({ track }) => {
    const activated = track(store, "activated"); // If dependent needs this, it will set activated = true
    if (activated) {
      setTimeout(() => {
        store.rx = createRx(store, store.value);
      }, propagationDelay);
    }
  });

  return store;
}
```

Child stores will react to `rx` being defined, and parent stores will react to `activated` being set to `true`. `useStream$` will explain this more. 

### `useStream$`

Before we look at `useStream$`, we need to consider another situation: Combined observables. 

Let's say `results$` switch maps to another observable defined with a Qwik store. In order to define `results$`, we need to trigger the inner observable's code to be fetched. My first thought was to create a `subscribed` property so observables below could set it and trigger the code to load, but that would be confused with actual RxJS subscriptions, and they're not the same thing—the inner observable needs to be defined before it gets an actual subscription. So, let's make an `activated` property, and have the same `useWatch$` that defines the observable track it. 

This is what that behavior looks like:

![RxJS in Qwik Demo 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2hqigau2n1m15ajrossd.gif)

The red outline is when the store has been activated. Again, I've added a 2000 delay so you can see how all of this works. Normally there will be no delay. 

Now we're ready for the code that makes this work. `useStream$` also uses a lot of utilities, so let's go through those.

`qrlToRx` is a function that converts Qwik's QRL promises into observables. This is useful whenever you need to pass unserializable code into an RxJS stream through a function. 

```tsx
// utils/qrl-to-rx.function.ts
import { QRL } from "@builder.io/qwik";
import { from, Observable, switchAll } from "rxjs";

export function qrlToRx<T>(fn: QRL<() => Observable<T>>) {
  return () => from(fn()).pipe(switchAll());
}
```

`useRxStore` is a function that defines a Qwik store for RxJS, but without the `BehaviorSubject` logic:

```tsx
// utils/use-rx-store.function.ts
import { useStore } from "@builder.io/qwik";
import { RxStore } from "./rx-store.type";

export function useRxStore<T>(initialState: T): RxStore<T> {
  const store = useStore({
    rx: undefined,
    value: initialState,
    activated: false,
  });

  return store;
}
```

Alright, now we're ready for the big `useStream$` function. I added comments throughout to explain what it does, since it's so big.

```tsx
// utils/use-stream.function.ts
import {
  implicit$FirstArg,
  noSerialize,
  QRL,
  useWatch$,
} from "@builder.io/qwik";
import { Observable, tap } from "rxjs";
import { propagationDelay } from "./propagation-delay.const";
import { qrlToRx } from "./qrl-to-rx.function";
import { RxStore } from "./rx-store.type";
import { useRxStore } from "./use-rx-store.function";

export function useStreamQrl<T>(
  fn: QRL<() => Observable<T>>,
  [initialState, deps]: [T, RxStore<any>[]]
): RxStore<T> {
  const store = useRxStore(initialState);

  useWatch$(({ track }) => {
    // Tracking store.activated and all dep rx's
    // Will not run until a child activates store or a parent rx gets defined
    // If activated or parent defined, activate all parents
    // If all parents defined, define this

    const activated = track(store, "activated");
    const [someDefined, allDefined, allActivated] = deps.reduce(
      (acc, source) => {
        const rx = track(source, "rx");
        acc[0] = acc[0] || !!rx;
        acc[1] = acc[1] && !!rx;
        acc[2] = acc[2] && source.activated;
        return acc;
      },
      [false, true, true]
    );

    if (someDefined) {
      setTimeout(() => {
        store.activated = true;
      }, propagationDelay);
    }

    if (activated && !allActivated) {
      // Activated from parent => someDefined becomes true
      // Activated from child => activated becomes true
      setTimeout(() => {
        deps.forEach(source => {
          source.activated = true;
        });
      }, propagationDelay);
    }

    if (allDefined) {
      setTimeout(() => {
        store.activated = true;
        store.rx = noSerialize(
          qrlToRx(fn)().pipe(tap(value => (store.value = value)))
        );
      }, propagationDelay);
    }
  });

  return store;
}

export const useStream$ = implicit$FirstArg(useStreamQrl);
```

That was complicated, so hopefully it makes sense! Comment if anything is unclear.

### `useSubscribe`

Finally, we need to subscribe to the stream. 

Again, this one has some utilities. It's not obvious yet, but there's a reason I split them out. But first let's look at the hook itself:

```tsx
import { useStore, useWatch$ } from "@builder.io/qwik";
import { RxStore } from "./rx-store.type";
import { subscribe } from "./subscribe.function";

export function useSubscribe<T>(store: RxStore<T>) {
  const outputStore = useStore({ value: store.value });

  useWatch$(args => {
    subscribe(args, store, outputStore);
  });

  return outputStore;
}
```

So we have an input `RxStore` (with an `rx` property) to subscribe to, and a new Qwik store that will contain the results. 

Here's `subscribe`:

```tsx
// utils/subscribe.function.ts
import { RxStore } from "./rx-store.type";
import { WatchArgs } from "./watch-args.type";

export function subscribe<T>(
  { track, cleanup }: WatchArgs,
  store: RxStore<T>,
  outputStore: { value: T }
) {
  const rx = track(store, "rx");
  if (rx) {
    const sub = rx.subscribe((val) => (outputStore.value = val));
    cleanup(() => sub.unsubscribe());
  }
}
```

## Example #2: Client subscription

What if we have a timer we want to have start as soon as the component is visible on the client? We can define a `useSubscribeClient$` hook that does the same thing as the `useSubscribe$` above, but also has a `useClientEffect$` that sets the parent stream's store's `activated` property. Here's what that looks like:

![RxJS in Qwik Demo 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0hjt9igslalqxkr18kj.gif)

And here's the implementation. It's the same as `useSubscribe`, but we add a client effect to activate the parent observable immediately:

```tsx
import { useClientEffect$ } from "@builder.io/qwik";
import { RxStore } from "./rx-store.type";
import { useSubscribe } from "./use-subscribe.function";

export function useSubscribeClient<T>(store: RxStore<T>) {
  useClientEffect$(() => {
    store.activated = true;
  });
  return useSubscribe(store);
}
```

How do we define the timer though? We'll treat it as an independent observable with a subscription of its own, but by default we'll wait for it to be activated by observables below. We can call it `useStreamToSubject$`. Here's how I implemented it:

```tsx
// utils/use-stream-to-subject.function.ts
import { implicit$FirstArg, QRL, useWatch$ } from "@builder.io/qwik";
import { Observable } from "rxjs";
import { qrlToRx } from "./qrl-to-rx.function";
import { RxStore } from "./rx-store.type";
import { streamToSubject } from "./stream-to-subject.function";
import { useSubject } from "./use-subject.function";

export function useStreamToSubjectQrl<T>(
  fn: QRL<() => Observable<T>>,
  initialState: T
): RxStore<T> {
  const store = useSubject(initialState);
  useWatch$((args) => streamToSubject(args, store, qrlToRx(fn)()));
  return store;
}
export const useStreamToSubject$ = implicit$FirstArg(useStreamToSubjectQrl);
```

There's only one function in there we haven't gone over yet:

```tsx
// utils/stream-to-subject.function.ts
import { BehaviorSubject, finalize, Observable } from "rxjs";
import { RxStore } from "./rx-store.type";
import { WatchArgs } from "./watch-args.type";

export function streamToSubject<T>(
  { cleanup, track }: WatchArgs,
  store: RxStore<T>,
  obs$: Observable<T>
) {
  track(store, "activated");
  const sub = obs$
    .pipe(finalize(() => (store.rx as BehaviorSubject<T>)?.complete?.()))
    .subscribe(n => (store.value = n));
  cleanup(() => sub.unsubscribe());
}
```

As you can see, it waits to be activated from below, then it calls the function passed into it to define the observable. An example usage:

```tsx
const intervalStore = useStreamToSubject$(() => interval(3 * 1000), 0);
```

## Example 3: Independent observable emits

What if we don't want to load the entire RxJS stream until the timer emits? As mentioned at the beginning of this article, I don't have a general solution to lazy-loading segments of the same observable graph independently, but for the case of an observable that can be treated independently and obviously has a subscription, we can define a hook that will subscribe to an observable and assign the emitted values to a Qwik store's `value` property, similar to the way we handled user input. Is this a good idea, from a code organization point of view? I have no idea. But here's how the behavior looks:

![RxJS in Qwik Demo 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81qufqk1ajm1cgkc1vmu.gif)

And here's the implementation:

```tsx
// utils/use-stream-to-subject-client.function.ts
import { implicit$FirstArg, QRL, useClientEffect$ } from "@builder.io/qwik";
import { Observable } from "rxjs";
import { qrlToRx } from "./qrl-to-rx.function";
import { RxStore } from "./rx-store.type";
import { streamToSubjectClient } from "./stream-to-subject-client.function";
import { useSubject } from "./use-subject.function";

export function useStreamToSubjectClientQrl<T>(
  fn: QRL<() => Observable<T>>,
  initialState: T
): RxStore<T> {
  const store = useSubject(initialState);
  useClientEffect$((args) => streamToSubjectClient(args, store, qrlToRx(fn)()));
  return store;
}
export const useStreamToSubjectClient$ = implicit$FirstArg(
  useStreamToSubjectClientQrl
);
```

Very similar to `useStreamToSubject`, but it calls `streamToSubjectClient` instead, and does it inside a `useClientEffect$` so it runs immediately. Here's that implementation:

```tsx
// utils/stream-to-subject-client.function.ts
import { Observable } from "rxjs";
import { RxStore } from "./rx-store.type";
import { WatchArgs } from "./watch-args.type";

export function streamToSubjectClient<T>(
  { cleanup }: WatchArgs,
  store: RxStore<T>,
  obs$: Observable<T>
) {
  const sub = obs$.subscribe(n => (store.value = n));
  cleanup(() => sub.unsubscribe());
}
```

It's probably not worth having in a separate file, but I made it early on and never changed it. It's fine how it is I guess.

## Example 4: Qwik store as observable

Qwik stores are synchronously reactive, so there will be many features that don't need RxJS. However, if we do end up needing some asynchronous reactivity from RxJS, wouldn't it be nice if we could just add it and use a regular Qwik store as if it were an RxJS Qwik store?

We'd want to be able to treat any property as an observable, so we'll need to provide both the store and the property we want to "chain off of" with our RxJS code. So the code would look like this:

```tsx
const normalQwikStore = useStore({ prop: 'val' });
const rxStoreFromQwik = useSubjectFromStore([normalQwikStore, 'prop']);
// or
const store = useStore({ value: 'val' });
const rxStore = useSubjectFromStore(store);
```

Now `rxStore` is ready to be used inside `usePipe$`. 

And here's that implementation:

```tsx
// utils/use-subject-from-store.function.ts
import { useWatch$ } from "@builder.io/qwik";
import { RxStore } from "./rx-store.type";
import { useSubject } from "./use-subject.function";

export interface UseSubjectFromStore<T> {
  <Prop extends string, Store extends Record<Prop, T>>(
    input: { value: T } | [Store, Prop]
  ): RxStore<T>;
}

export function useSubjectFromStore<T>(
  input: Parameters<UseSubjectFromStore<T>>[0]
) {
  const isArray = Array.isArray(input);
  const initialValue = isArray ? input[0][input[1]] : input.value;
  const store = useSubject(initialValue);

  useWatch$(({ track }) => {
    const value = isArray ? track(input[0], input[1]) : track(input, "value");
    store.value = value;
  });

  return store;
}
```

## Example 5: Operator only

![Server happy client happy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fz1h82m1arf47ev7fkdr.png)

RxJS has 114 operators. While its primary benefit is enabling code to be structured reactively, those 114 operators can add a lot of convenience. So what if we want to mostly just use Qwik stores, but sometimes just use a single operator from RxJS now and then?

This approach basically ignores RxJS's laziness by assuming everything already has a subscription. For inputs it takes in an operator, then a Qwik store and property tuple; and it outputs another Qwik store, with the `value` property containing the emitted value. Like this:

```tsx
const store = useStore({ n: 0 });
const nEven = usePipe(() => filter(n => n % 2), [store, 'n']);
```

Again, we can assume a default property of `value` for the input store. 

We are only taking in a single operator, but we could use with custom operators to give us more RxJS in a single store:

```tsx
const results = usePipe$(
    () => stream =>
      stream.pipe(
        tap(console.log),
        map(n => n * 10),
        filter(n => n >= 100),
      ),
    normalQwikStore,
  );
```

Now, here's the implementation:

```tsx
// utils/use-pipe.function.ts
import { implicit$FirstArg, QRL, useStore, useWatch$ } from "@builder.io/qwik";
import { OperatorFunction } from "rxjs";
import {
  UseSubjectFromStore,
  useSubjectFromStore,
} from "./use-subject-from-store.function";

export function usePipeQrl<T, U>(
  operatorQrl: QRL<() => OperatorFunction<T, U>>,
  input: Parameters<UseSubjectFromStore<T>>[0]
) {
  const rxStore = useSubjectFromStore(input);
  const outputStore = useStore({ value: undefined as any }); // Final operator output

  useWatch$(({ track, cleanup }) => {
    const rx = track(rxStore, "rx");
    if (rx) {
      operatorQrl().then(operator => {
        const sub = operator(rx).subscribe(
          value => (outputStore.value = value)
        );
        cleanup(() => sub.unsubscribe());
      });
    }
  });

  return outputStore;
}

export const usePipe$ = implicit$FirstArg(usePipeQrl);
```

This might be the most promising way to use RxJS in Qwik today, since it puts Qwik's reactivity at the center. It could be that the ideal approach to asynchronous reactivity in Qwik isn't pure RxJS, but primarily a Qwik hook model. With hooks, calling them implies interest in their values, so it's similar to subscribing; just not as granular. So if that becomes the new "subscription" model, then RxJS just becomes a utility library to allow us to code declaratively for async logic without having to implement all of that all on our own up front (see [my previous article](https://dev.to/mfp22/why-rxjs-compatibility-matters-gl2)). And since it's Qwik-centric, over time, each `usePipe$` call could be replaced with a more Qwik-native solution, maybe involving signals, to get more fine-grained rendering. 

This might be awesome. 

Follow me if you want to hear when I figure out more stuff with this. 

---

And that's what I have for now. 

Now I'll include the notes for the ideal solution that I never found. 

---

# Notes
## The ideal solution 

*Note: Qwik seems to be rapidly evolving still. Will anything with this RxJS stuff need to be redesigned? How can RxJS work optimally with signals? Apparently unresolved promises will soon be serializable in Qwik. What does that look like? It might be worth waiting for the dust to settle a little more before investing too much time into anything yet. However, these notes might remain relevant.* 

To implement the ideal behavior, we need to treat each segment of the RxJS steam independently, with its own internal subscription, and output to a Qwik store so we can trigger a `useWatch$` to load and run the next RxJS segment after the current segment has done its work. 

We also need to be able to load the streams from the bottom up, so the initial subscription information can propagate correctly. For example, if an observable is defined using a `switchMap`, the inner observable may not immediately be subscribed to, so on the client we should ignore the events at the top of that stream until the `switchMap` runs and a subscription gets passed up.

So, the overall process is this: A `useSubscribe` hook initially runs on the server, generating a trail of subscription state up to the tops of the streams. The app is serialized, including these subscription trails. When the app is resumed on the client, only RxJS streams that are on the subscription trails will be loaded, and only once they're required to process new events. As values trickle down the RxJS pipes, RxJS code at each segment is loaded, and if the streams are combined, the subscriptions are propagated up to the tops of the adjacent streams as needed, in the same process that was initially done for the first stream. 

I imagine a syntax like this: 

```tsx
const search = useSubject$('');
const debouncedSearch = useStream$(() => rx => rx(search).pipe(debounceTime(500)));
```

`rx` allows us to avoid providing the Qwik stores as explicit dependencies, making this syntax more DRY; actually the only way we can provide Qwik stores as proper dependencies is implicitly inside the Rx stream anyway, because we don't want to eagerly subscribe to anything. Consider this example:

```tsx

const mode = useSubject$(Mode.Simple); // enum
const simple = useObservable(simple$);
const complex = useObservable(complex$);

const results$ = useStream$(() => rx => rx(mode).pipe(
  switchMap(m => m === Mode.Condense ? rx(simple$): rx(complex$)),
));
```

We would not want Qwik to set up a subscription to `complex$` unless `mode.value` was set to `Mode.Complex`. 

The only way to properly propagate subscriptions up to the right Qwik stores is by using RxJS's own subscription mechanism. 

So, how do we know when RxJS actually subscribes and perform a side-effect? That would be with `defer`. Then we can use a `finalize` to clean up afterwards. 

So, this can all run on the server initially, and set up the `track`s correctly, then only awake on the client when what's being tracked changes. But what changes? When a parent observable is defined, we're still not interested in it yet—we only care when it emits a value. So we need to set a Qwik store property at the end of that, so it can be tracked. So for each RxJS stream, we need a store to go along with it, and a subscription like this 

```tsx
store.sub = stream$.subscribe(value => store.value = value)
```

So, `rx` needs to track the parent store's `value` property. 

But here's a tricky situation on top of all of this: What if the event that causes the RxJS to first load on the client ends up passing a value downstream that changes the subscriptions to other stores? How do we update the Qwik stores so they update these subscriptions and don't load unnecessary RxJS or result in bugs from unexpected RxJS work? 

We need a global context that tracks every store and its subscriptions. That means each store needs a unique ID. That can be provided in context as well, so whenever we use an RxJS hook, we need to call `useContext` to get an id for the new Qwik store corresponding with the RxJS pipe. Then whenever RxJS subscriptions are updated, we'll update this global Qwik store with the appropriate subscription information. This can be tracked, so a store can detect if something suddenly subscribes to it. Then it can activate its RxJS and set its `value` property. 

So `rx` might have an implementation that would return something like this:

```tsx
defer(() => {
  // Get parent store from global context; increment subscriber count
  // Track parent store `value` property
  // Add store id to a dep list in this store

  // return BehaviorSubject representing parent 
}).pipe(finalize(() => {
  // Get parent store from global context; decrement subscriber count
  // Set store.value to undefined?
  // Remove store id from dep list in this store
  // 
}))
```

I forgot to explain why I have this comment in there: /`/ Add store id to a dep list in this store`. Why does the current store also need a list of the stores it depends on?   We need to call `track` inside our `defer` so that Qwik will call our `useWatch$` on the client when the parent observable emits a value. This gives us the ability to load the RxJS and define it on the client. We need to set aside the store dependency IDs before subscribing to the new stream, because the initial values on the client might cause a change in dependencies, and we'll need to update the global context with that changed subscription information. But once we define the RxJS stream, it's not going to be called again; so when a parent store updates a value, it's not going to be tracked next time around. This could potentially be a problem. Maybe we can also track the dependencies and use that to track the global context... but does that mean we need to store the RxJS emitted values in the global context as well? And can we really do tracking this dynamically? And is this efficient enough?

At this point my thinking gets really muddled. This was very much a work in progress. I've gone between a few different architectures, but I don't feel that I'm up to this challenge at the moment. I'm going to wait for Qwik to mature more before investing more time into this. For now I'm going to focus on [StateAdapt](https://state-adapt.github.io/) again.

My goal here was just to get my thoughts out there, and if they're useful to anyone who wants to try harder than I have, I hope they at least provide a starting point. I might be close or far from a good solution. But I don't even feel like I've considered all possible scenarios or challenges.

### Other challenges 

What about streams that complete? How do you update subscriptions when that happens?

How do you handle errors?

Other challenges?


## Implementation

Every time a new subscription occurs, we need to load the entire upstream RxJS chain. To know which exact path needs to be loaded, we need to load and define the RxJS stream at each segment first, and follow the subscription to whatever upstream RxJS it goes to. Since the next level up isn't defined yet, we need a way to intercept the reference and subscription to the next segment's observable, and increase a subscriber count in that stream's Qwik store (which will trigger the same process for that segment) and return an observable of that Qwik store's `value` property, which will eventually contain the output of that segment's stream. 

and at each segment add to a subscriber count in a Qwik store. Every time a finalize gets called, we'll decrement the subscriber count. When an app is serialized, it will

As long as this subscribe count isn't rendered in JSX, Qwik will not call the cleanup functions associated with them when the app is serialized

---

Propagating and storing subscription data is not a simple task. For each segment of lazy-loaded RxJS, we need a Qwik store that can react to changes in the Qwik stores containing its upstream observables. However, depending on how the RxJS is defined, not all the upstream Qwik stores should have a subscription passed on to them. 

But we also don't want to just load the entire RxJS stream to pass the subscription up in the natural RxJS way either, because again, we'd have to load the entire stream to do that. 

---

I may have mixed in some article notes with that as well, but that's okay. You know my mindset a bit more maybe.

Thanks for reading! Go check out [StateAdapt](https://github.com/state-adapt/state-adapt) and give it a star :)