shreyaa
shreyaa

Reputation: 93

Create reducer to update state for different components in redux

I am creating this UI using react and redux. Below is the image of the UI. This is image of UI

Now it currently displays the data when 'Categories' is clicked. Then when I click on unmapped link ,it shows unmapped products of 'Categories'. But when I click on 'Addons' and then on unmapped link ,it still shows the unmapped products of 'Categories'. How do I write the reducer so that it shows the unmapped products of 'Addons' as well. In my react main file I use (this.props.menu_items) that's why it shows the data of 'Categories' when clicked unmapped after Addons.


This is my reducer file.

import { AppConstants } from '../constants';

const initialState = {
  state: [],
  menu_items: [],
  menu_items_copy: [],
  addon_items: [],
  unmapped: false,
 };

   export default (state = initialState, action) => {
     switch (action.type) {
     case AppConstants.getMenuItems:
      return {
       ...state,
      }
   case AppConstants.getMenuItemsSuccess:
      return {
      ...state,
     menu_items: action.menu_items,//This contains the data showed when 
    // 'categories' is clicked
     menu_items_copy: action.menu_items,
     unmapped: false,
     }
   case AppConstants.getAddonsItems:
      return {
       ...state,
     }
   case AppConstants.getAddonsItemsSuccess:
     return {
     ...state,
     menu_items: action.addon_items,//Here I update the data to addons data
    }

   case AppConstants.showAllProducts:
     return {
      ...state,
     menu_items: action.menu_items,
     unmapped: false
   }

  case AppConstants.getUnmappedMenuItemsSuccess:
    return {
    ...state,
    unmapped: true,
    menu_items: state.menu_items_copy.filter((item) => {-->How do I write 
      here for action.addon_items also
      return (item.productList.length == 0)
     })
    }
  case AppConstants.hideError:
    return {
      ...state,
     error: null
   }
 default:
  return state
 }
 };

Upvotes: 0

Views: 543

Answers (1)

alechill
alechill

Reputation: 4522

The only state I would change via reducer when unmapped is clicked would be to set unmapped: true / false.

There is no need to filter the items array and store it back into the state, as you already have all the info you need to derive your combined items at the point where you pass it to the view.

Have a read about derived state and selectors here http://redux.js.org/docs/recipes/ComputingDerivedData.html

In order to do this you would use a selector to combine the relevant parts of your state to produce a single list of items that is derived from both the items arrays, depending on the unmapped flag. The reselect library is a great helper to do this while memoising for performance, it will only recompute if any of the inputs change, otherwise returns the previously cached value

import {createSelector} from 'reselect'

const selectMenuItems = state => state.menu_items
const selectAddonItems = state => state.addon_items
const selectUnmapped = state => state.unmapped

const selectItemsToShow = createSelector(
  selectMenuItems, 
  selectAddonItems, 
  selectUnmapped, 
  (menuItems, addonItems, unmapped) => {
    // if unmapped is set - combine all items and filter the unmapped ones
    if (unmapped) {
      return menuItems.concat(addonItems).filter(item => !item.productList.length)
    }
    // else just return the menu items unfiltered
    return menuItems
  }
)

// this selector can then be used when passing data to your view as prop elsewhere
// or can be used in `connect` props mapping as in the linked example)
<ItemsList items={selectItemsToShow(state)} />

Upvotes: 1

Related Questions