Signal Store — Series 3

Preview — 3 of 10 questions

This meta-reducer is registered app-wide. Besides every genuine application action ([Cart] Add Item, and so on), what else does analytics.track end up receiving, and why does that matter?

javascript
export function analyticsMetaReducer(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
  return (state, action) => {
    analytics.track(action.type);
    return reducer(state, action);
  };
}
ANgRx's own internal lifecycle actions too — @ngrx/store/init, @ngrx/effects/init, and similar framework-dispatched actions pass through every meta-reducer exactly like any other action, since a meta-reducer sits in front of the entire reducer pipeline with no built-in filtering. An analytics meta-reducer without an explicit filter ends up sending tracking events for these internal, framework-level actions too, polluting real usage analytics with noise the application never actually triggered
BNothing else — meta-reducers only ever see actions explicitly dispatched by application code
COnly actions dispatched from effects, never ones dispatched directly from components
DOnly actions matching a whitelist configured in provideStore's metaReducers array

Beyond general tidiness, what concrete problem does storing authorId (a reference) avoid, that storing a full nested author: Author object on every post would create?

javascript
// Normalized
interface State { posts: EntityState<Post>; authors: EntityState<Author>; }
interface Post { id: string; authorId: string; title: string; }

// Nested (the alternative)
interface Post { id: string; author: Author; title: string; }
AIf the same author has written multiple posts, the nested approach stores a separate copy of that author's data on every one of their posts — updating the author's name means finding and updating it in every single post that embeds a copy, and any place that missed one now shows stale, inconsistent data for "the same" author. The normalized approach stores the author exactly once, referenced by id from as many posts as need it, so updating that one Author entity instantly reflects correctly everywhere it's referenced
BNested objects are simply not supported by TypeScript's type system
CNested objects can't be serialized to JSON for Redux DevTools
DThere's no actual difference; both approaches behave identically for all practical purposes

Why does the second form avoid the referential-instability problem the first one has?

javascript
// Problematic: a new selector instance every render
function selectHeroById(id: string) {
  return createSelector(selectHeroEntities, (entities) => entities[id]);
}
AThe parameterized form is defined exactly once, at module scope, as a single selector — there's no factory function creating a brand-new selector (with its own fresh memoization cache) on every call. The id is instead passed in as props at select()-call time, and NgRx's selector machinery handles comparing props across calls, so the one shared selector instance's memoization stays meaningful and useful across every component using it, rather than every caller getting an isolated, single-use selector instance
BIt doesn't actually fix anything; both forms have identical performance characteristics
CThe parameterized form disables memoization entirely, trading it for guaranteed correctness instead
DBoth forms are identical; the second is purely a stylistic preference with no functional difference

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.