---
title: Capsules
description: Learn the basics behind capsules in ReArch.
---

# Capsules
Capsules are the most fundamental building block of ReArch.
Capsules en-_capsulate_ some data, thus their name.

<Info>
  Data here encompasses more than just raw data; it also includes functions.
  This is an important consideration, as ReArch is highly functional.
</Info>


## The Theory
When you start designing an application,
it is often easiest to think in terms of the data you are modeling
and how that data interacts with other data in your application.
Consequently, when you go to create some non-trivial state,
chances are high that it depends on some other form of state in your application.


### Functions of State
Capsules let you think in this manner by themselves being *functions of state*
(and more generally, side effects, but more on that later).
This may sound wishy-washy, so here is a concrete example:
```dart title="Basic count and countPlusOne capsules"
int countCapsule(CapsuleHandle use) => 0;

int countPlusOneCapsule(CapsuleHandle use) => use(countCapsule) + 1;
```
Notice here how `countPlusOneCapsule` *consumes* `countCapsule`;
i.e., `countPlusOneCapsule` is a function of state, where the state is the current `countCapsule`!

As you can see in the above example, capsules are nothing special;
every capsule is merely a function that consumes a `CapsuleHandle`.
A capsule's power is derived from from _how you use the `CapsuleHandle`_ within the capsule.

<Info>
In Dart, there is also another way to define capsules (via a syntactic sugar):
```dart title="Example capsule written via syntactic sugar"
final Capsule<ValueWrapper<int>> myIntCapsule = capsule((use) => use.data(0));
```
Note that this is exactly the same as writing the capsule out as a function,
as the `capsule()` function is simply defined as:
```dart title="Definition of the capsule() function"
Capsule<T> capsule<T>(Capsule<T> cap) => cap;
```
You are welcome to use whichever version you prefer in your projects; they are 100% interoperable.
</Info>


### Immutability
Capsules were designed with the intent that the data they produce is *immutable*.
In Rust, this is enforced via never providing a `&mut` to any capsule's data.
In Dart, it is up to you to make sure you do not directly mutate a capsule's data
without using one of the side effects (again, more on side effects later).


## The `CapsuleHandle`
So what is this magical `CapsuleHandle` parameter all capsules consume?
The `CapsuleHandle` is actually not magic at all;
it is just a temporary lease from the `Container` (next page) to build a capsule's data,
given the state of the container.

More specifically, the `CapsuleHandle` is a composition of two other types:
- The `CapsuleReader` allows the capsule to read the current data of itself and other capsules
- The `SideEffectRegistrar` allows the capsule to register side effects

<Warning>
Do not use a `CapsuleHandle` across an asynchronous gap
(i.e., used after any `await`s or in a callback) in Dart!
Although you may not see issues immediately,
know that you may encounter issues when in more complex situations.
(Rust does not have this issue due to its ownership rules.)
</Warning>


### The `CapsuleReader`
The `CapsuleReader` provides the familiar `use(...)` syntax in Dart and `get(...)` in Rust.
<CodeGroup title="Using The CapsuleReader">
  ```dart
  int countCapsule(CapsuleHandle _) => 0;

  int countPlusOneCapsule(CapsuleHandle use) {
    return use(countCapsule) + 1;
  }
  ```

  ```rust
  fn count_capsule(_: CapsuleHandle) -> u8 {
      0
  }

  fn count_plus_one_capsule(CapsuleHandle { mut get, .. }: CapsuleHandle) -> u8 {
      // Please note the following distinction in syntax based on toolchain;
      // the nightly syntax will be used in all remaining examples for clarity.
      // get.as_ref(count_capsule) + 1 // Works in stable and nightly
      get(count_capsule) + 1           // Works in nightly only with "experimental-api" feature
  }
  ```
</CodeGroup>


### The `SideEffectRegistrar`
The `SideEffectRegistrar` provides the familiar set of `use.fooBar()` side effects in Dart 
and `register(effect1(), effect2())` in Rust.
See [the docs on side effects](/core/effects) for more.


## Generic Capsules
As a reminder, a capsule is just a function that consumes a `CapsuleHandle` and returns some data.
Because of this realization, *generic* functions that consume `CapsuleHandle`s are *also* capsules.
This can lead to some pretty interesting patterns, a (somewhat useless) example of which is below.
<CodeGroup title="Generic capsules example">
  ```dart
  List<T> Function(T, int) repeatedItemFactory<T>(CapsuleHandle use) {
    return (itemToRepeat, repetitions) => List.generate(repetitions, (_) => itemToRepeat);
  }

  // ...
  final repeatedIntsFactory = container.read(repeatedItemFactory<int>);
  final repeatedStringsFactory = container.read(repeatedItemFactory<String>);
  final repeatedStrings = repeatedStringsFactory("this will be repeated 1234 times!", 1234);
  ```

  ```rust
  fn repeated_item_factory<T: Clone>(
      _: CapsuleHandle,
  ) -> impl Fn(T, usize) -> Vec<T> + Clone + Send + Sync {
      |item_to_repeat, repetitions| (0..repetitions).map(|_| item_to_repeat.clone()).collect()
  }

  // ...
  let repeated_ints_factory = container.read(repeated_item_factory::<i32>);
  let repeated_strs_factory = container.read(repeated_item_factory::<&str>);
  let repeated_strs = repeated_strs_factory("this will be repeated 1234 times!", 1234);
  ```
</CodeGroup>
<Info>
  Notice how the capsule above returns a *function*;
  this is a very useful pattern that will be revisited again in the pages on the factories/actions.
</Info>


## Reducing Builds
Reducing builds is a useful optimization that can be done in ReArch through:
1. Conditionally using capsules
2. Inline capsules


### When Do You Need to Reduce Rebuilds?
Consider the following capsule.

<CodeGroup title="Capsule with excessive rebuilds">
  ```dart
  FooBar expensiveOperationUsingCount(CapsuleHandle use) {
    final count = use(countCapsule);
    final isWatching = use(isWatchingCapsule);
    return someExpensiveOperation(isWatching ? count : null);
  }
  ```

  ```rust
  fn expensive_operation_using_count(CapsuleHandle { mut get, .. }: CapsuleHandle) -> FooBar {
    let count = get(count);
    let is_watching = get(is_watching);
    return some_expensive_operation(if is_watching { Some(count) } else { None });
  }
  ```
</CodeGroup>

This looks ok until you realize that whenever `count` changes,
`someExpensiveOperation`/`some_expensive_operation` will be called again,
even if `isWatching`/`is_watching` is false!
These extra rebuilds can be removed with the following.

<CodeGroup title="Limiting extra rebuilds">
  ```dart
  FooBar expensiveOperationUsingCount(CapsuleHandle use) {
    if (use(isWatchingCapsule)) {
      // Having this use within a branch will stop rebuilds caused by
      // countCapsule when isWatching is false.
      return someExpensiveOperation(use(countCapsule));
    }
    return someExpensiveOperation(null);
  }
  ```

  ```rust
  fn expensive_operation_using_count(CapsuleHandle { mut get, .. }: CapsuleHandle) -> FooBar {
    if get(is_watching) {
      // Having this get within a branch will stop rebuilds caused by
      // count when is_watching is false.
      some_expensive_operation(Some(get(count)))
    } else {
      some_expensive_operation(None)
    }
  }
  ```
</CodeGroup>

However, this simple conditional watching is not always enough to reduce some builds;
sometimes, `someExpensiveOperation` is a `Widget` rebuild in Flutter,
where the rebuild depends upon some non-encapsulable data (such as a key in a large collection).
For situations like this, you likely need *inline capsules*
to prevent rebuilding potentially thousands of Widgets displaying the current data in a collection
whenever just a single entry is modified.


## Inline Capsules
Inline capsules are just regular capsules (which, as a reminder, are just functions),
but are unique because they are *closures*.

<Info>
  While you can *define* inline capsules in Rust, I have not found a useful application of them yet,
  mostly because ReArch for Rust does not have an accompanying UI framework.
  Thus, the rest of this section only applies to Dart at the moment.
</Info>

There are two ways to create inline capsules:
- `myCapsule.map()`, a convenience extension method that creates an inline capsule
- Manually (but caution must be used here)!

Each solves slightly different use-cases.
However, when possible, it is best to make new *intermediary* top-level capsules instead,
and let ReArch use its own optimizations to limit rebuilds.
Remember, capsules are cheap, and are designed to be composed.
You should only very rarely use inline capsules,
and when you do, make sure they are *very cheap* (ideally just a constant-time look-up).


### `.map()`
The example Flutter app utilizes `.map()` to reduce some rebuilds,
so see that for a more full example.
However, here is a simple example to give you an idea of how `.map()` works.

```dart title="Inline capsule example with .map()"
class MyListItem extends RearchConsumer {
  const MyListItem(this.listIndex, {super.key});

  final int listIndex;

  Widget build(BuildContext context, WidgetHandle use) {
    // With this inline capsule, we only rebuild when the data at
    // myList[listIndex] changes, instead of the whole myList.
    final dataAtIndex = use(
      // This creates a new inline capsule that gets a particular index of myList:
      myListCapsule.map((myList) => myList[listIndex]),
    );
    return Text('$dataAtIndex');
  }
}
```


### Manual Inline Capsules
Contrary to the `.map()` convenience method, manual inline capsules define the closure explicitly.
This is beneficial when your inline capsule depends on >1 other capsules,
which should be rather rare.

<Warning>
  Only use manual inline capsules when your inline capsule needs to `use`
  *multiple* different capsules,
  as manual inline capsules are easier to mess up and cause leaks!
</Warning>

Here's the previous example, but rewritten to use a manually defined inline capsule.
```dart title="Manual inline capsule example"
class MyListItem extends RearchConsumer {
  const MyListItem(this.listIndex, {super.key});

  final int listIndex;

  Widget build(BuildContext context, WidgetHandle use) {
    // With this inline capsule, we only rebuild when the data at
    // myList[listIndex] changes, instead of the whole myList.
    final dataAtIndex = use(
      // This creates a new inline capsule that gets a particular index of myList:
      (CapsuleReader use) => use(myListCapsule)[listIndex],

      // While the following works, it is considered a bad practice
      // (keep reading for an explanation):
      // (use) => use(myListCapsule)[listIndex],
    );
    return Text('$dataAtIndex');
  }
}
```

Notice above how the parameter is declared as `CapsuleReader use`;
while you actually get a full `CapsuleHandle` here for the inline capsule,
you must be careful to not use any side effects (`use.fooBar()`) or *you will cause leaks*.
Thus, it is considered to be a best practice to prevent yourself from using side effects
by declaring the parameter type as `CapsuleReader` instead of letting it get inferred
as a `CapsuleHandle` (which is what happens if you do not explicitly specify `CapsuleReader`).
You can actually use this same pattern for your regular capsules too
if you wish to declare that it cannot use side effects (i.e., is an idempotent capsule),
but that is not documented elsewhere in order to not confuse beginners.
