Skip to content

Commit

Permalink
feat: Ability to read a signal value without subscribing to it via th…
Browse files Browse the repository at this point in the history
…e `peek` function.
  • Loading branch information
cesarParra committed Dec 6, 2024
1 parent 8998ac6 commit 8dc1db3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 0 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,33 @@ $effect(() => console.log(counter.value));

> ❗ DO NOT use `$effect` to update the signal value, as it will create an infinite loop.
## Peeking at the signal value

If the rare case that you have an effect that needs to read of a signal without subscribing to it, you can
use the signal's `peek` function to read the value.

```javascript
import { $signal, $effect } from "c/signals";

const counter = $signal(0);

$effect(() => console.log(counter.peek()));
```

This can be useful when you need to update the value of a signal based on its current value, but you want
to avoid causing a circular dependency.

```javascript
const counter = $signal(0);
$effect(() => {
// Without peeking, this kind of operation would cause a circular dependency.
counter.value = counter.peek() + 1;
});
```

Note that you should use this feature sparingly, as it can lead to bugs that are hard to track down.
The preferred way of reading a signal is through the `signal.value`.

## Error Handling

When unhandled errors occur in a `computed` or `effect`, by default, the error will be logged to the console through
Expand Down
10 changes: 10 additions & 0 deletions src/lwc/signals/__tests__/effect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,14 @@ describe("effects", () => {

expect(customErrorHandlerFn).toHaveBeenCalled();
});

test("can change and read a signal value without causing a cycle by peeking at it", () => {
const counter = $signal(0);
$effect(() => {
// Without peeking, this kind of operation would cause a circular dependency.
counter.value = counter.peek() + 1;
});

expect(counter.value).toBe(1);
});
});
8 changes: 8 additions & 0 deletions src/lwc/signals/__tests__/signals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ describe("signals", () => {
const signal = $signal(0);
expect(signal.brand).toBe(Symbol.for("lwc-signals"));
});

test("allow for peeking the value without triggering a reactivity", () => {
const signal = $signal(0);
const spy = jest.fn(() => signal.value);
const value = signal.peek();
expect(spy).not.toHaveBeenCalled();
expect(value).toBe(0);
});
});


0 comments on commit 8dc1db3

Please sign in to comment.