Sitethief
Sitethief

Reputation: 770

How do I add data from one reducer to existing data in the store?

When a user searches in my ReactJS app he gets results. When the user scrolls I want to load in the next set of data in an infinite scroll using react-waypoint. What works is the following:

What I can't get working is appending this to the existing items. What I have now is a seperate reducer which loads all the extra data into nextItems. But I want to simply add this to the existing items. I've tried the following in my items.js reducers. But all this does is add an undefined entry to the nextItems array. Somehow I can't wrap my head around this.

export function items(state = [], action) {
    switch (action.type) {
        case 'ITEMS_FETCH_DATA_SUCCESS':
            return action.items;

        default:
            return state;
    }
}
export function nextItems(state = [], action) {
    switch (action.type) {
        case 'ITEMS_FETCH_NEXT_DATA_SUCCESS':
            return [...state.items, ...action.nextItems];

        default:
            return state;
    }
}

I have the feeling that I have to combine both reducers and split them on type, or fix this in the item.js actions file. But I don't know how to get this working, and everything I tried got me either confusing errors, or nothing at all.

My actions: https://pastebin.com/zEPsxhb8

My reducers: https://pastebin.com/dSNFFff0

Upvotes: 0

Views: 1064

Answers (2)

You can use my function. For example you can move this function to Utils file or other service.

{ ... // this is your reducer 
  return mergeObjectArrays(state, items, options.key || 'id');
}

mergeObjectArrays(arr1, arr2, key = 'id') {
  const res = arr1.slice();

  for (let item of arr2) {
    let index;
    if (typeof key === 'string') {
      index = arr1.findIndex((itm) => itm[key] == item[key]);
    }
    else {
      index = arr1.findIndex((itm) => {
        let eq = true;
        for (let i = 0; i < key.length; i++) {
          eq = eq && itm[key[i]] == item[key[i]]
        }
        return eq;
      });
    }

    if (index === -1) res.push(item);
    else res[index] = item;
  }

  return res;
}

Upvotes: 1

Dan Mason
Dan Mason

Reputation: 2327

You should be able to acheive this with Array.prototype.concat.

export function nextItems(state = [], action) {
    switch (action.type) {
        case 'ITEMS_FETCH_NEXT_DATA_SUCCESS':
            return Object.assign({}, 
                state.items, 
                state.items.concat(action.nextItems)
            );

        default:
            return state;
    }
}

Upvotes: 1

Related Questions