Mutation
Import:
import { mutation, withMutation } from '@ng-query/ngrx-signals';
import { rxMutation } from '@ng-query/ngrx-signals-rxjs';
What is a Mutation?
A mutation in Signal Store is mainly used to update a server state (with POST, PUT, DELETE requests). Mutations are declarative and reactive, type-safe, and can be linked to queries for automatic UI updates, optimistic updates, and error handling.
How to Use a Mutation
Define a mutation in your Signal Store using the withMutation feature. Specify the mutation name, a function mutation or rxMutation, and optionally, options for linking the mutation to queries (optimistic updates, reloads, etc, check the next section for more info).
DANGER
Both mutation and rxMutation relies on signal source, only the last value emitted in very short period of time is considered. (A possible evolution is creating a withRxMutation associated with rxMutationthat relies on observables). For more info
Example
const Store = signalStore(
withMutation('updateUser', () =>
mutation({
method: (id: string) => ({ id }),
loader: ({ params }) => updateUserOnServer(params),
})
)
);
// Inject the store and use the mutation
const store = inject(Store);
store.mutateUpdateUser('5'); // Triggers the mutation
const status = store.updateUserMutation.status(); // 'idle', 'loading', 'resolved', 'error'mutation vs rxMutation
Both mutation and rxMutation are used to fetch server state in Signal Store, but they differ in how they handle data sources and reactivity:
mutation: Based on
resourceis designed for promise-based or synchronous data loaders. It expose allresourcefunctionalities.rxMutation: Based on
rxResourceis designed for observable-based data streams (RxJS). It expose allrxResourcefunctionalities.
rxMutation Options
The rxMutation function provides flexible options for configuring how your mutation receives parameters and streams data:
method: A function that returns the mutation parameters. This is typically. This function is exposed into the store
typescriptmethod: (id: string) => ({ id });params$: An Observable that emits parameters for the mutation. Use this if your parameters come from an RxJS stream.
typescriptparams$: of({ id: '5' });param: A function that returns the mutation parameters. This is typically. This function is exposed into the store
typescriptparam: signal({ id: '5' });stream: A function that receives the current parameters and returns an Observable of the mutation result. This is where you connect to your mutation source (REST, GraphQL, WebSocket, etc.).
typescriptstream: ({ params }) => updateUser$(params);
Example Usage
// Using method (function or signal)
rxMutation({
method: (id: string) => ({ id }),
stream: ({ params }) => updateUserStream$(params), // returns Observable<User>
});
// Using params$ (observable)
rxMutation({
params$: of({ id: '5' }),
stream: ({ params }) => updateUserStream$(params), // returns Observable<User>
});Notes
- You can use either
methodorparams$orparam, but not both at the same time. - The
streamfunction is required and should always return an Observable. - The mutation will automatically update its value and status whenever the parameters or the stream emit new values.
When to use each
- Use
mutationfor single-shot updates (REST, GraphQL, etc.) or when you only need the result once. - Use
rxMutationfor real-time updates, websockets, polling, or any scenario where the mutation source is an Observable and can emit multiple values over time.