Skip to content

Commit

Permalink
Merge pull request #529 from jviide/docs
Browse files Browse the repository at this point in the history
docs: document effect cleanups & comment why ES5-style prototypes are used
  • Loading branch information
marvinhagemeister committed Mar 15, 2024
2 parents 62b7a64 + 590a466 commit ec5fe42
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 21 deletions.
53 changes: 36 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,6 @@ effect(() => {

Note that you should only use `signal.peek()` if you really need it. Reading a signal's value via `signal.value` is the preferred way in most scenarios.

### `untracked(fn)`

In case when you're receiving a callback that can read some signals, but you don't want to subscribe to them, you can use `untracked` to prevent any subscriptions from happening.

```js
const counter = signal(0);
const effectCount = signal(0);
const fn = () => effectCount.value + 1;

effect(() => {
console.log(counter.value);

// Whenever this effect is triggered, run `fn` that gives new value
effectCount.value = untracked(fn);
});
```

### `computed(fn)`

Data is often derived from other pieces of existing data. The `computed` function lets you combine the values of multiple signals into a new signal that can be reacted to, or even used by additional computeds. When the signals accessed from within a computed callback change, the computed callback is re-executed and its new return value becomes the computed signal's value.
Expand Down Expand Up @@ -158,6 +141,25 @@ dispose();
surname.value = "Doe 2";
```

The effect callback may return a cleanup function. The cleanup function gets run once, either when the effect callback is next called _or_ when the effect gets disposed, whichever happens first.

```js
import { signal, effect } from "@preact/signals-core";

const count = signal(0);

const dispose = effect(() => {
const c = count.value;
return () => console.log(`cleanup ${c}`);
});

// Logs: cleanup 0
count.value = 1;

// Logs: cleanup 1
dispose();
```

### `batch(fn)`

The `batch` function allows you to combine multiple signal writes into one single update that is triggered at the end when the callback completes.
Expand Down Expand Up @@ -220,6 +222,23 @@ batch(() => {
// Now the callback completed and we'll trigger the effect.
```

### `untracked(fn)`

In case when you're receiving a callback that can read some signals, but you don't want to subscribe to them, you can use `untracked` to prevent any subscriptions from happening.

```js
const counter = signal(0);
const effectCount = signal(0);
const fn = () => effectCount.value + 1;

effect(() => {
console.log(counter.value);

// Whenever this effect is triggered, run `fn` that gives new value
effectCount.value = untracked(fn);
});
```

## License

`MIT`, see the [LICENSE](./LICENSE) file.
20 changes: 16 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,13 @@ function addDependency(signal: Signal): Node | undefined {
return undefined;
}

// @ts-ignore internal Signal is viewed as a function
// @ts-ignore: "Cannot redeclare exported variable 'Signal'."
//
// A function with the same name is defined later, so we need to ignore TypeScript's
// warning about a redeclared variable.
//
// The class is declared here, but later implemented with ES5-style prototypes.
// This enables better control of the transpiled output size.
declare class Signal<T = any> {
/** @internal */
_value: unknown;
Expand Down Expand Up @@ -239,7 +245,13 @@ declare class Signal<T = any> {
}

/** @internal */
// @ts-ignore internal Signal is viewed as function
// @ts-ignore: "Cannot redeclare exported variable 'Signal'."
//
// A class with the same name has already been declared, so we need to ignore
// TypeScript's warning about a redeclared variable.
//
// The previously declared class is implemented here with ES5-style prototypes.
// This enables better control of the transpiled output size.
function Signal(this: Signal, value?: unknown) {
this._value = value;
this._version = 0;
Expand Down Expand Up @@ -319,7 +331,7 @@ Signal.prototype.peek = function () {
};

Object.defineProperty(Signal.prototype, "value", {
get() {
get(this: Signal) {
const node = addDependency(this);
if (node !== undefined) {
node._version = this._version;
Expand Down Expand Up @@ -596,7 +608,7 @@ Computed.prototype._notify = function () {
};

Object.defineProperty(Computed.prototype, "value", {
get() {
get(this: Computed) {
if (this._flags & RUNNING) {
throw new Error("Cycle detected");
}
Expand Down

0 comments on commit ec5fe42

Please sign in to comment.