1

I need to be able to switch items in an array on state using the immutability helper so as to not mutate state directly.

This is the behavior I am looking to achieve (i.e. switching positions 2 with 3)

[
    { key: 'banana'},
    { key: 'apple'},
    { key: 'orange'}
]

to become

[
    { key: 'banana'},
    { key: 'orange'},
    { key: 'apple'}
]

The code below is generating what I thought was going to accomplish this

immutableFruit = {}

let tempFruit = fruits[2]
immutableFruit[2] = { $set: fruits[1] }
immutableFruit[1] = { $set: tempFruit }

this.setState({fruits: immutableFruit})

When logging this to the console I get what I expect

1:
  $set: { key: 'orange' }
2:
  $set: { key: 'apple' }

So, in my mind, the state should reflect this change, but it doesn't something I didn't expect to, it switches one of the items, but fails to replace the other.

This is what the resulting state array actually looks like

[
    { key: 'banana'},
    { key: 'orange'},
    { key: 'orange'}
]

So, in short, I end up with two items in the list that are identical.

Is $set not the correct way to do this? When looking through the immutability helper documentation I didn't find any examples of this behavior or commands that perhaps are better fits for swapping elements in an array

1
  • Did you find a solution to this? Commented Feb 5, 2019 at 13:23

2 Answers 2

1

One solution is to splice twice:

const fruits = [
    { key: "banana" },
    { key: "apple" },
    { key: "orange" }
];

console.log(fruits);

const swappedAppleAndOrange = 
    update(
        update(
            fruits, { $splice: [[1, 1, fruits[2]]] }
        ),
        { $splice: [[2, 1, fruits[1]]]}
    );

console.log(swappedAppleAndOrange);

This logs:

0: {key: "banana"}
1: {key: "apple"}
2: {key: "orange"}

0: {key: "banana"}
1: {key: "orange"}
2: {key: "apple"}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you Cheruvim for checking. I ended up doing something along these lines I believe
This might be helpful, too: medium.com/front-end-weekly/…
0

Adding to @cherouvim's solution:

let fruits = [
    { key: "banana" },
    { key: "apple" },
    { key: "orange" }
];


function moveUp(key) {
    const idx = fruits.findIndex(f => f.key === key)
    if (idx < 1) return;

    fruits = update(
        update(
            fruits, { $splice: [[idx - 1, 1, fruits[idx]]] }
        ),
        { $splice: [[idx, 1, fruits[idx - 1]]]}
    );
}

function moveDown(key) {
    const idx = fruits.findIndex(f => f.key === key)
    if (idx === -1 || idx > fruits.length - 1) return;

    fruits = update(
        update(
            fruits, { $splice: [[idx + 1, 1, fruits[idx]]] }
        ),
        { $splice: [[idx, 1, fruits[idx + 1]]]}
    );
}

moveUp("apple");
console.log(fruits);

moveDown("apple");
console.log(fruits);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.