1
votes

I am trying to use stackoverflow api to make my first react redux project. I need to maintain a state like the following:

{
    selectedTag: reactjs,
    selectedSortOrder: activity,
    items:[]
}

My reducer is given below:

const initialState = {
  selectedTag: 'C#',
  selectedSortOrder: 'activity', items: []
}

function SelectTag(state = initialState, action) {
  switch (action.type) {
    case SELECTTAG:
      //  console.log(state);
      return Object.assign({}, state, { selectedTag: action.selectedTag });
    default:
      return state;
  }
}

function SelectSortOrder(state = initialState, action) {
  switch (action.type) {
    case SELECTSORTORDER:
      //console.log(state);
      return Object.assign({}, state, { selectedSortOrder: action.selectedSortOrder });
    default:
      return state;
  }
}

function ReceivePosts(state = { items: [] }, action) {
  switch
  (action.type) {
    case RECEIVESORTEDPOSTS:
    case RECEIVEPOST:
      console.log(state);
      return Object.assign({}, state, { items: action.items })
    default:
      return state
  }
}

const rootReducer = combineReducers({ ReceivePosts, SelectTag, SelectSortOrder })

And mapStateToProps is:

const mapStateToProps = (state) => {
  const selectedTag = state.SelectTag.selectedTag;
  const items = (state.ReceivePosts.items);
  const tags = (state.ReceiveTags.tags);
  const selectedSortOrder = state.SelectSortOrder.selectedSortOrder;
  return {selectedTag, items, tags, selectedSortOrder};
}

I have 2 problems here:

a. State does not remember all the data. For eg. suppose I select the tag first and then get items, my state has only items. SelectedTag is not set in the state.

b. I am not sure why mapStateToProps needs the reducer name. Eg: const selectedTag = state.SelectTag.selectedTag;

Actually it should be state.selectedTag. But my code expects the reducer name "SelectTag" to fetch the state value.

What am I doing wrong?

2
It doesn’t look like you have your reducers hooked up right. Are you using combineReducers?Ryan Allred
Yes Ryan, I am using combineReducers. Edited the post with the combineReducers code.metis

2 Answers

0
votes

You haven't configured your reducers correctly. The initialState is assigned to all of your reducers which isn't required

 const initialState={   
    selectedTag:'C#',  
    selectedSortOrder:'activity',
    items:[]
 }

function SelectTag(state = initialState.selectedTag, action){  
  switch(action.type){ 
     case SELECTTAG:
       return action.selectedTag
     default:
       return state;   
  }
}

function SelectSortOrder(state = initialState.selectedSortOrder, action){  
  switch(action.type){
     case SELECTSORTORDER:
       return action.selectedSortOrder
     default:
       return state;
    }
}

function ReceivePosts(state = {items:[]}, action){   
   switch(action.type){
       case RECEIVESORTEDPOSTS:
       case RECEIVEPOST:
         console.log(state);
         return Object.assign({}, state, {items:action.items})
       default:
         return state
     }
 }

const rootReducer = combineReducers({ReceivePosts, SelectTag, SelectSortOrder})

And in mapStateToProps you would use it like

const mapStateToProps = (state) => {
  const selectedTag = state.SelectTag;
  const items = (state.ReceivePosts.items);
  const tags = (state.ReceiveTags.tags);
  const selectedSortOrder = state.SelectSortOrder;
  return {selectedTag, items, tags, selectedSortOrder};
}
0
votes

1. Try this code change

const initialState = {
  selectedTag: 'C#',
  selectedSortOrder: 'activity', 
  items: []
}

function SelectTag(state = initialState.selectedTag, action) {
  switch (action.type) {
    case SELECT TAG:
      return {
        ...state,
        selectedTag: action.selectedTag
      }
    default:
      return state;
  }
}

function SelectSortOrder(state = initialState.selectedSortOrder, action) {
  switch (action.type) {
    case SELECTSORTORDER:
      return {
        ...state,
        selectedSortOrder: action.selectedSortOrder
      }
    default:
      return state;
  }
}

function ReceivePosts(state = { items: [] }, action) {
  switch (action.type) {
    case RECEIVESORTEDPOSTS:
    case RECEIVEPOST:
      return {
        ...state,
        items: action.items
      }
    default:
      return state
  }
}

const rootReducer = combineReducers({ ReceivePosts, SelectTag, SelectSortOrder });

2. I am not sure why mapStateToProps needs the reducer name. Eg: const selectedTag = state.SelectTag.selectedTag;

Its because when you use combinereducers, you are combining multiple slices of data, then you need to specify the slice from which you want to fetch the data.

const rootReducer = combineReducers({ 
    receivePosts = ReceivePosts, 
    selectTag = SelectTag, 
    selectSortOrder = SelectSortOrder 
});

Issue: You have not configured your initialstate properly, you are using the same initialstate in SelectTag and also in SelectSortOrder, if the initial state is same then why do you need two reducers?