Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(store): add possibility to dispatch Signal<Action> #4600

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

rainerhahnekamp
Copy link
Contributor

A type of Signal can be passed to dispatch:

class BookComponent {
  bookId = input.required<number>();
  bookAction = computed(() => loadBook({id: this.bookId()}));

  store = inject(Store);

  constructor() {
    this.store.dispatch(this.bookAction);
  }
}

The benefit is that users no longer need to use an effect to track the Signal. The Store handles this internally.

If dispatch receives a Signal it returns an EffectRef, allowing manual destruction.

By default, the injection context of the caller is used. If the call happens outside an injection context, the Store will use its own injection context, which is usually the root injector.

It is also possible to provide a custom injector as the second parameter:

this.store.dispatch(this.bookAction, {injector: this.injector});

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[ ] Bugfix
[x] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:

What is the current behavior?

Users need to manually track Signals via effect

Closes #4537

What is the new behavior?

Does this PR introduce a breaking change?

[ ] Yes
[x] No

Copy link

netlify bot commented Nov 19, 2024

Deploy Preview for ngrx-io ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 8ecac43
🔍 Latest deploy log https://app.netlify.com/sites/ngrx-io/deploys/673fc9de2e87dd0008b0e110
😎 Deploy Preview https://deploy-preview-4600--ngrx-io.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@rainerhahnekamp rainerhahnekamp force-pushed the feature/store/signal-actions branch 2 times, most recently from f70110f to dc049ef Compare November 19, 2024 23:36
A type of Signal<Action> can be passed to dispatch:

```typescript
class BookComponent {
  bookId = input.required<number>();
  bookAction = computed(() => loadBook({id: this.bookId()}));

  store = inject(Store);

  constructor() {
    this.store.dispatch(this.bookAction);
  }
}
```
The benefit is that users no longer need to use an effect to track the Signal.
The Store handles this internally.

If `dispatch` receives a `Signal` it returns an `EffectRef`, allowing manual
destruction.

By default, the injection context of the caller is used. If the call happens
outside an injection context, the Store will use its own injection context,
which is usually the root injector.

It is also possible to provide a custom injector as the second parameter:
```typescript
this.store.dispatch(this.bookAction, {injector: this.injector});
```
Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
I left some comments for the syntax in the docs.

projects/ngrx.io/content/guide/store/actions.md Outdated Show resolved Hide resolved
projects/ngrx.io/content/guide/store/actions.md Outdated Show resolved Hide resolved
projects/ngrx.io/content/guide/store/actions.md Outdated Show resolved Hide resolved
projects/ngrx.io/content/guide/store/actions.md Outdated Show resolved Hide resolved
@rainerhahnekamp
Copy link
Contributor Author

Thanks @timdeschryver, I've applied all your changes

`dispatch` now accepts a function that returns an `Action`. Providing a `Signal<Action>` will still be possible (`Signal` is also a function).

I had to rename the type `FunctionIsNotAllowed` to `NoActionCreator`.

Previously, `FunctionIsNotAllowed` was used to prevent passing functions to `dispatch`, but the primary intent was to forbid `ActionCreator`.

```typescript
store.dispatch(loadBook); // 👎
store.dispatch(loadBook({id: 1})); // 👍
```

As the name says, `NoActionCreator` now explicitly forbids only `ActionCreator`. Functions are fine. Otherwise, the new feature would not be possible.
@rainerhahnekamp
Copy link
Contributor Author

dispatch now accepts a function that returns an Action. Providing a Signal<Action> will still be possible (Signal is also a function).

I had to rename the type FunctionIsNotAllowed to NoActionCreator.

Previously, FunctionIsNotAllowed was used to prevent passing functions to dispatch, but the primary intent was to forbid ActionCreator.

store.dispatch(loadBook); // 👎
store.dispatch(loadBook({id: 1})); // 👍

As the name says, NoActionCreator now explicitly forbids only ActionCreator. Functions are fine. Otherwise, the new feature would not be possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature: Add support to the NgRx Store for dispatching actions that read signals
3 participants