Search code examples
angularecmascript-6reduxngrxngrx-store

How to properly create a new state in Redux?


Working with Redux in my Angular app, and simply creating a new state in each Case inside the Switch Statement. However, even though my code works just fine I don't feel comfortable with the way I'm cloning my object inside each case, so is there a better or cleaner way of cloning it? How can I improve the Case statement? Thanks in advance!.

Here's my

Interface:

export interface AppState {
  session: {},
  uiState: {
    summary: {
      summaryDetail: {
        headerTitle: string;
        expandSummaryDetailPanel: boolean;
        showSummaryDetail: boolean;
        someProperty: string;
       }
       showSummaryTab: boolean;
    }
  }
}; 

Initial State:

export const initialState: AppState = {
  session: {},
  uiState: {
    summary: {
      summaryDetail: {
        headerTitle: 'new title',
        expandSummaryDetailPanel: false,
        showSummaryDetail: false,
        someProperty: ''
      },
      showSummaryTab: false,
    }
  }
};

Switch Statement:

export function appReducer(state = initialState, action: appActions.AppAction) { 

 case appActions.EXPAND_SUMMARY_DETAIL_PANEL: {
  return {
    ...state,
    uiState: {
      summary: {
        ...state.uiState.summary,
        summaryDetail: {
          ...state.uiState.summary.summaryDetail,
          expandSummaryDetailPanel: action.payload
        }
      }
    }
  }
 }
}

Solution

  • You would need additional libraries to avoid repeating the nesting if your state actually has to be this deeply nested. I'd try to model the state differently (flatter) first. But if that is somehow not an option, you can do this:

    case appActions.EXPAND_SUMMARY_DETAIL_PANEL:
        // Find a library that clones objects or use something like immutablejs.
        const newState = deepClone(state);
        newState.uiState.summary.summaryDetail.expandSummaryDetailPanel = action.payload;
        return newState;
    

    A few notes:

    • The properties in your state repeat the word "summary" a lot. Would state.summary.detail.expandPanel also work and be expressive enough?
    • uiState reads like you're expressing where the state is used, but redux doesn't have to be concerned about this. This type of mapping happens in mapStateToProps. Or at the very least shorten it to state.ui.