Raj Rj
Raj Rj

Reputation: 3577

return new state, don't mutate it. Am i doing it right way?

I am rendering a tabList, onclick of any tab it will be highlighted. I am achieving this by checking a selected attribute. Everytime a tab is clicked I am changing selected to true/false in my reducer.

myTabsReducer should not mutate but return a new array.

Am I doing it right way? As per documentation We should not mutate state (should not alter state). In my case I'm altering my reducer. Is it Ok to do it or is there any other way to achieve it?

export const myTabsReducer = (id) => {
      return [
        {
            id: 1,
            name:"My Tab 1",
            selected: id==1?true:false
          },
          {
            id: 2,
            name:"My Tab 2",
            selected: id==2?true:false
          },
          {
            id: 3,
            name:"My Tab 3",
            selected: id==3?true:false
          }
      ]
    }

const myActiveTabReducer = (state = {}, action) => {  
  switch (action.type) {
    case SELECT_PLAN_TAB:
      return action.payload
    default:
      return 1;
  }
}

const allReducers = (state = {}, action) => {
    return {
      allTabs: myTabsReducer(myActiveTabReducer(state, action)),
  }
}

Upvotes: 1

Views: 111

Answers (2)

Matteo Frana
Matteo Frana

Reputation: 579

It would be much better to have your state in this way:

const initialState = {
  tabs: [
    { id: 1, name: 'Tab 1' },
    { id: 2, name: 'Tab 2' }
  ],
  selectedTab: 1
}

so that your reducer changes only the selectedTab property on "SELECT_PLAN_TAB":

const activeTabReducer = (state = initialState, action) => {
  switch (action.type) {
    case SELECT_PLAN_TAB:
      return {
        ...state,
        selectedTab: action.payload
      };
    default:
      return state;
  }
}

Then, if you need the tabs array with the selected property for each tab, I would use a selector: see http://redux.js.org/docs/recipes/ComputingDerivedData.html

Upvotes: 2

Denis Ivanov
Denis Ivanov

Reputation: 905

You are not mutating the array. Every time reducer is called you generate a new array.

const foo1 = allReducers({}, {type:' SELECT_PLAN_TAB', payload: 1})
const foo2 = allReducers({}, {type:' SELECT_PLAN_TAB', payload: 1})

console.log(foo1.allTabs === foo2.allTabs) // false

You should be careful, because this function will always return new instance even if input stays the same. This means that shallow equality check will fail and depending on how you consume this store, your component will always re-render.

Upvotes: 0

Related Questions