0

I have seen 3 forms of reducers:

// Form 1
function reducer(state, action) {
  if (state === undefined)
    return state = [];

  // handle action.type
  // ...
}

// Form 2
function reducer(state, action) {
  if (state === undefined)
    state = [];

  // handle action.type
  // ...
}

// Form 3
function reducer(state = [], action) {

  // handle action.type
  // ...
}

Are they all the same? Form 1 and Form 2 differ by Form 1 immediately returning the initial state without looking at and taking care of action.type at all.

And I think Form 2 and Form 3 are exactly the same, using default parameter value.

Can any claim be substantiated by any official docs or specs? It think it means, the very first time a reducer is called, action.type won't be anything meaningful.

nonopolarity
  • 146,324
  • 131
  • 460
  • 740

3 Answers3

0

In a Redux reducer, if state is not defined, can you immediately return the initial state?

yes, we can.

But for this, you don't need to check for undefined or any other non-empty check.

switch default statement will handled it very smoothly.

function reducer(state, action) {

  switch(action.type){
      //rest case
      default:
      return state;
  }
}

// Form 2
function reducer(state, action) {

    switch(action.type){
        //rest case
      default:
      return state;
    }
}
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53
0

You may simply use: createReducer from redux-starter-kit

Which is also been used in this demo from microsoft

A utility function that allows defining a reducer as a mapping from action type to case reducer functions that handle these action types. The reducer's initial state is passed as the first argument.

The body of every case reducer is implicitly wrapped with a call to produce() from the immer library. This means that rather than returning a new state object, you can also mutate the passed-in state object directly; these mutations will then be automatically and efficiently translated into copies, giving you both convenience and immutability.

@param initialState — The initial state to be returned by the reducer.
@param actionsMap — A mapping from action types to action-type-specific case redeucers.

Usage

export const LocalStorageReducer = createReducer<Store['localStorage']>(
  new LocalStorage(), // <= where you define the init value of this state
  {
    storeLocalStorageInput(state, action) {
      return state = {...state, [action.payload.item]: action.payload.value};
    },
    clearLocalStorageInput(state, action) {
      return state = new LocalStorage();
    },
  }
);

export const reducer = combineReducers({
  localStorage: LocalStorageReducer,
...

type of createReducer

(alias) createReducer<LocalStorage, CaseReducers<LocalStorage, any>>(initialState: LocalStorage, actionsMap: CaseReducers<LocalStorage, any>): Reducer<LocalStorage, AnyAction>
import createReducer

sample of state

export class LocalStorage {
  /**
   * Editing plan id in planner pages
   */
  planId: string | undefined;
  /***
   * Touched id list
   */
  touchedIdList: Array<string>;
  constructor() {
    this.planId = undefined;
    this.touchedIdList = Array<string>();
  }
}

There are already developed methods to do those things by libs, no need to manually do it again in most situation.

keikai
  • 14,085
  • 9
  • 49
  • 68
0
  • Redux initializes it dispatches a "dummy" action to fill the state. Please check this docs
  • Reducers are not allowed to return undefined under any condition, It can return null if necessary

Technically all three are same, as first time the reducers will called with dummy, state is no longer undefined at Form 1. On subsequent call, it will be called with meaningful action from your application code and as state = [] at that time, it will check the action.type