Pascal
Pascal

Reputation: 75

NgRx reducer function with condition

I have a side effect that detects the browser language and dispatches a browserLanguageSupported action if it is a language that my application can handle.

Now I have following reducer function that only updates the states preferredLanguage property in case it is not defined already. This is important because there are other actions that update this state property and I do not want a late browserLanguageSupported action to overwrite such a state update.

export interface State {
  preferredLanguage: AppLanguage | undefined;
  rehydrationComplete: boolean;
}

export const initialState: State = {
  preferredLanguage: undefined,
  rehydrationComplete: false
};

export const reducer = createReducer(
  initialState,
  on(LanguageActions.browserLanguageSupported, (state, {browserLanguage}) => {
    if (!state.preferredLanguage) {
      return {...state, preferredLanguage: browserLanguage};
    }
    return state;
  })
);

Now for my question: Is it good practice to have such a condition in a reducer operator? The function itself is still pure. But I am not sure if it is good design or if I should solve it differently, lets say by adding state slice selection in the side effect that dispatches this action.

Btw. the reason I am not setting it directly in the initial state is because I get the browser language from an angular service and I am not sure if it is even possible to set initial feature state from service injection?

Best regards, Pascal

Upvotes: 2

Views: 1902

Answers (2)

KOVIKO
KOVIKO

Reputation: 1379

As long as the rejection (or mutation) of the data is irrelevant to the chain of actions & effects, this is absolutely valid.

However, it's worth noting that if the action in question triggers an effect which triggers an action, the triggered action will not know whether the data was rejected (or mutated) without checking the state—which is exactly what this pattern is attempting to avoid.

So, if you wanted to be able react to that rejection (or mutation), you would want to handle this in the effect. But, if you would proceed in exactly the same manner regardless of the result, then it belongs reducer.

Upvotes: 0

timdeschryver
timdeschryver

Reputation: 15505

I would to this the same way, so you get a đź‘Ť from me. Adding a slice of the state into the effect just adds needless complexity. The reducer contains the state, and it's OK to add logic to see if state needs to be updated or not.

Also, let's say you need to add this logic into another action/effect. Having it in the reducer makes it easier to reuse if it's needed. Otherwise you end up with duplicate logic.

Upvotes: 3

Related Questions