72 lines
2.2 KiB
Markdown

# computed
A `computed` is a [subscribable](./subscribable.md), computed value expression. It takes any number
of dependent inputs and provides one output. Subscribers are only notified if the computed value
changes. `computed` forms the core of a logic graph.
## Behavior
A `computed` takes any kind of dependency but if a dependency is a [subscribable](./subscribable.md)
then the `computed` will subscribe to it such that the `computed` will be marked as _dirty_ when any
that subscribable value changes. Whenever the `computed` is read from, if will recompute its result
if the _dirty_ flag has been set, otherwise it just return the stored result from the last time it
computed.
Unlike [KnockoutJS](http://knockoutjs.com/) and [Vuejs](https://vuejs.org), Reactimal's `computed`
requires explicit dependency expression to help avoid dependency loops and allow code retain
readability as it grows.
## Usage
### Creation
Creates a computed instance. Internally the passed computation function is called once to establish
the initial value.
```js
const showDialog = computed(
(inVP, shouldShow) => inVP && shouldShow, // computation function
[inViewport, shouldShow] // array of subscribable dependencies
);
```
### Read
Call the computed to receive the computed value. The value will be computed if any upstream
dependencies have changed.
```js
if (showDialog()) {
/* showDialog() is truthy */
}
```
### Provide a hash function for complex result types
When the computed result is a type that is not determined to be equal with simple equality (===),
provide a hash function to the `hashableComputed` type to create a computed that will reduce the
result value to a value that can be compared with the identity operator before comparison. The
computed result value will still be stored unmodified.
```js
function hashSet(_a) {
if (_a instanceof Set) {
return Array.from(_a.keys())
.sort()
.map(k => `${(typeof k).substr(0, 1)}:${encodeURIComponent(k)}/`)
.join('?');
}
return _a;
}
const computedSet = hashableComputed(hashSet);
function _intersection(a, b) {
return new Set([...a].filter(x => b.has(x)));
}
const a = prop(new Set([1, 2]), hashSet);
const b = prop(new Set([2, 3]), hashSet);
const intersection = computedSet(_intersection, [a, b]);
```