diff --git a/packages/frptools/README.md b/packages/frptools/README.md index 5e2b5fd..9aa64c6 100644 --- a/packages/frptools/README.md +++ b/packages/frptools/README.md @@ -39,11 +39,11 @@ inViewport(false); ### Subscribe to changes -Call the subscribe method with a callback that will be called when the observable is changed to a -different value. +Call the `subscribe` method with a callback that will be called when the observable is changed to a +different value. The returned function can be called to unsubscribe from the observable. ```js -inViewport.subscribe(console.log.bind(console)); +const unsubscribe = inViewport.subscribe(console.log.bind(console)); ``` # [computed](./src/computed.js) @@ -54,8 +54,8 @@ derive value from observables rather than store value and hence cannot be set di ## Behavior A `computed` will subscribe to its dependencies in such a way that it will be marked as _dirty_ when -any dependency changes. Whenever it is read from, if will recompute if it is dirty, otherwise it -just return the stored result from the last time it computed. +any dependency changes. Whenever it is read from, if will recompute its result if the _dirty_ flag +is set, otherwise it just return the stored result from the last time it computed. ## Usage @@ -77,3 +77,33 @@ if (showDialog()) { ``` Call it to receive the stored value, recomputing if necessary. + +### Subscribe to changes + +Call the subscribe method with a callback that will be called when the computed result changes to a +different value. The returned function can be called to unsubscribe from the observable. + +```js +const unsubscribe = inViewport.subscribe(console.log.bind(console)); +``` + +**NOTE**: Subscribing to a computed forces it to recompute every time an upstream dependency +changes. This could negatively performance if it depends on multiple values that change sequentially +and the computation function is non-trivial. For example: + +```js +const inViewport = observable(false); +const shouldShow = observable(false); + +const showDialog = computed((inVP, shouldShow) => inVP && shouldShow, [inViewport, shouldShow]); + +inViewport(true); // showDialog marked as dirty but does not recompute its stored result. +shouldShow(true); // showDialog is already marked as dirty. Nothing else happens. +showDialog(); // showDialog recomputes its stored result and unsets the dirty flag. + +showDialog.subscribe(console.log.bind(console)); + +inViewport(false); // showDialog result recomputed and `false` is written to the console. +shouldShow(false); // showDialog result recomputed, console.log is not called. +showDialog(); // showDialog does not recompute, console.log is not called. `false` is returned. +```