简体   繁体   中英

Update and reposition object in array in Redux reducer

const state = [
  {10: {a: 22, b: 33}},
  {12: {a: 20, b: 33}},
  {15: {a: 22, b: 34}},
  {5: {a: 21, b: 30}},
  {9: {a: 29, b: 33}},
]

State is an array of objects like above. When the app updates an object, the object should flow up to the first position.

Eg let's say that we take the second object above (with the primary key 12 ), and copy and update it so it looks like this:

{12: {a: 45, b: 33}}

And now we want to insert it to the array with the following result:

const state = [
  {12: {a: 45, b: 33}},
  {10: {a: 22, b: 33}},
  {15: {a: 22, b: 34}},
  {5: {a: 21, b: 30}},
  {9: {a: 29, b: 33}},
]

I understand how to update an object in an immutable fashion, but I cannot get my head around how to accomplish the above.

something like this perhaps?

 const state = [ {10: {a: 22, b: 33}}, {12: {a: 20, b: 33}}, {15: {a: 22, b: 34}}, {5: {a: 21, b: 30}}, {9: {a: 29, b: 33}}, ] // find the numerical index of the object with the specified "key" function findIndexOfKey(array, key){ return array.findIndex(function(el){return key in el}); } // modify object and move to front function editObjectAndMoveToFront(array, key, updatedValues){ // find index of object with key, for use in splicing var index = findIndexOfKey(array, key); // create the updated version of the specified object var originalObject = array[index]; var originalObjectValue = originalObject[key]; var editedObject = {}; editedObject[key] = Object.assign({}, originalObjectValue, updatedValues) // here is the new state, with the updated object at the front var newArray = [ editedObject, ...array.slice(0, index), ...array.slice(index + 1) ] return newArray } const newState = editObjectAndMoveToFront(state, 12, {a: 45, b: 33}) console.log(newState); 

You could use something like

// an update function, here it just adds a new key
// to the object
const update = (x) => ({
  ...x,
  hello: "world"
});

// a filter factory
const withId = (id) => (item) => Boolean(item[id]); // item with specific ids
const withoutId = (id) => (item) => !Boolean(item[id]); // others

const state = [
  {10: {a: 22, b: 33}},
  {12: {a: 20, b: 33}},
  {15: {a: 22, b: 34}},
  {5: {a: 21, b: 30}},
  {9: {a: 29, b: 33}},
];

const id = 5;
const newState = state
  .filter(withId(id))
  .map(update)
  .concat(state.filter(withoutId(id)));


console.log(JSON.stringify(newState, null, 4));

What this does is filtering the state between the items you want to update and the rest, apply the update to the selection and concat the untouched items to them.

Below another example on with the same idea which illustrates that you can perform the update on more than one item :

const markAsDone = (todo) => ({
  ...todo,
  done: true
});
const isInGroup = (group) => (todo) => todo.group === group;
const not = (predicate) => (x) => !predicate(x);

const isWork = isInGroup("work");
const notWork = not(isWork);

const state = [
  {
    todo: "go shopping",
    group: "life"
  },
  {
    todo: "go work",
    group: "work",
  },
  {
    todo: "go sleep",
    group: "life"
  }
];

// get work related todos, mark as done and 
// append to todo list
const newState = state
  .filter(notWork)
  .concat(state
    .filter(isWork)
    .map(markAsDone));


console.log(JSON.stringify(newState, null, 4));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM