# Caching

By default all ActiveJS [Units](/activejs/fundamentals/units.md) cache 2 values, and can be configured with minimum `1` or maximum `Infinity` for as many values as possible.

The cache is maintained in an `array`, at the last index we have the latest value, and at 0 index we have the first value. So the cache might look like this `[initialValue, v1, v2, ... , lastDispatchedValue]`. When the length becomes more than the `cacheSize`, values are removed from the start.

The way cache-navigation methods work is that, when you call one of them, let's say `goBack`, the Unit will emit the previous value from the cache, without modifying the cached values, so that the cached values would still be the same and in the same order. Only that the `cacheIndex` would now be `cacheIndex - 1`

Now if you dispatch a new value, this new value will be inserted directly after the current `cacheIndex` and all the values coming after that will be removed from the cache. So that the new value would become the last value in the cache. That's exactly how browser history works, we can open links after links, then we can go back and we can go forward, but as soon as we open a new link, that link becomes the last point in history, and now we can only go back.

However, if you don't want that to happen you can do an in-place cache replace by passing `{replaceCache: true}` flag to the dispatch method. It'll replace the value in cache at the current `cacheIndex`, just like we'd do `History.replaceState()` in case of browser history.

```typescript
const unit = new StringUnit({initialValue: 'a'}); 

// cache is ['a']

unit.goBack(); // won't work, returns false
unit.goForward(); // won't work, returns false

unit.dispatch('b'); // cache becomes ['a', 'b']
console.log(unit.value()) // logs 'b'

unit.goBack(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'a'

unit.goForward(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'b'

unit.jumoToStart(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'a'

unit.dispatch('d', {replaceCache: true}) // now the cache becomes ['d', 'b']
// 'a' is gone, instead of 'b'
console.log(unit.value()) // logs 'd'

unit.jump(1) // cache is still ['d', 'b']
console.log(unit.value()) // logs 'b'

// we can also access all the cached values
console.log(unit.cachedValues()) // logs ['d', 'b']

// or check the current cache index
console.log(unit.cacheIndex) // logs 0

// or check the count of cached values
console.log(unit.cachedValuesCount) // logs 2
```

## Cache navigation and immutability

When you use cache navigation with Units that store non-primitive values i.e. [DictUnit](/activejs/fundamentals/units/dictunit.md), [ListUnit](/activejs/fundamentals/units/listunit.md), and [GenericUnit](/activejs/fundamentals/units/genericunit.md), you will need to make sure to not mutate the value, otherwise cached value will also get mutated and `goBack`, `goForward` or other cache-navigation methods wouldn't work as expected, because the cached values would have been mutated, which is not what you expect.

To mitigate this problem you can simply make the Unit immutable, which will ensure that the cached values stay unaffected. See [Immutability](/activejs/guides/immutability.md) for how immutability works in ActiveJS Units.

Otherwise, you have to ensure that every time you dispatch a value it shouldn't have any reference to the Unit's current value, and when you access the Unit's value, you should make sure to not mutate this value in any way.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.activejs.dev/activejs/guides/caching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
