I'm currently working with ngrx and nrg-entity. I wonder what the best practices are for updating the store after a successful web request if the response doesn't contain the entity object that have to be stored.
Example:
// My state
export interface State extends EntityState<Book> {}
I make a web request to create a book. From backend I only get an id of the created book. By default you create a reducer to put that new created book in your store like so:
createReducer(
initialState,
on(BookActions.createBookSuccess, (state, { book}) =>
bookAdapter.addOne(book, { ...state, creating: false })
));
I see two options to return the new book to the reducer:
Is one of these options the way to move? Or is there a better way?
I hope I have been able to make my problem clear.
EDIT: I guess it's better to provide a practical example:
Actions:
export const createBook = createAction(
'[Book] Create Book',
props<{ book: NewBook }>()
);
export const createBookSuccess = createAction(
'[Book] Create book Success',
props<{ book: Book }>()
);
Effects:
createBook$ = createEffect(() =>
this.actions$.pipe(
ofType(AuftragActions.createBook),
switchMap((action) =>
this.bookDataService.createBook(action.book).pipe(
map((response) =>
// what to do, to get the new book object from backend?
BookActions.createBookSuccess({ book: response })
),
catchError((error) =>
of(AuftragActions.createAuftragFailure({ error }))
)
)
)
)
);
Reducers:
on(BookActions.createBook, (state) => ({
...state,
creating: true,
error: null,
})),
on(BookActions.createBookSuccess, (state, { auftrag }) =>
bookAdapter.addOne(book, { ...state, creating: false })
),
Data service:
createBook(book: NewBook): Observable<Book> {
// returns book id
}
loadByBookId(bookId: string): Observable<Book> {
// returns book;
So, how to extend the effect "createBook$" to emit the createBookSuccess-Action with the new created book from backend?
There are a lot of ways you can do this but my instinct would be to have the effect trigger another action/effect that gets and sets the next value. So your first effect returns something like this,
return [
..., //Whatever it already returns
LoadBookByIdEffect
]
Then your LoadBookIdEffect triggers an Action that sets the book value in state,
return SetBook({ book });
Here is a more detailed explanation of the syntax for chaining effects together like this,