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:
- In the dataservice createBook() method you make a second call "GetBookById()" when you get the id of the new book and return the book object.
- In the createBookSuccess effect you trigger a dataservice call "GetBookById()" and return the result (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,
Then your LoadBookIdEffect triggers an Action that sets the book value in state,
Here is a more detailed explanation of the syntax for chaining effects together like this,
Chain Actions in an Effect in @ngrx