ffxsam
ffxsam

Reputation: 27713

Deeply updating React state (array) without Immutable, any disadvantages?

I know using Immutable is a great way to deeply update React state, but I was wondering if there are any drawbacks I'm not seeing with this approach:

Assuming this.state.members has the shape Array<MemberType> where MemberType is { userId: String, role: String }.

If the user changes a user's role, the following method is executed:

  changeMemberRole = (userId, event, key, value) => {
    const memberIndex = _findIndex(this.state.members,
      (member) => member.userId === userId);

    if (memberIndex >= 0) {
      const newMembers = [...this.state.members];

      newMembers[memberIndex].role = value;
      this.setState({ members: newMembers });
    }
  };

Would there be any advantage to replacing this with Immutable's setIn, other than potentially more terse syntax?

Upvotes: 0

Views: 285

Answers (3)

martriay
martriay

Reputation: 5742

The difference between using or not Immutable.js is, of course, immutability¹ :)

When you declare const newMembers = [...this.state.members] you're copying an array of references, this is indeed a new array (modifying a direct child by index like 0,1,2 is not reflected) but filled with the same object references, so inner/deep changes are shared. This is called a shallow copy.

newMembers are not so new

Therefore any changes to any newMembers element are also made in the corresponding this.state.members element. This is fine for your example, no real advantages so far.

So, why immutability?

Its true benefits are not easily observed in small snippets because it's more about the mindset. Taken from the Immutable.js homepage:

Much of what makes application development difficult is tracking mutation and maintaining state. Developing with immutable data encourages you to think differently about how data flows through your application.

Immutability brings many of the functional paradigm benefits such as avoiding side effects or race conditions since you think of variables as values instead of objects, making it easier to understand their scope and lifecycle and thus minimizing bugs.

One specific advantage for react is to safely check for state changes in shouldComponentUpdate while when mutating:

// assume this.props.value is { foo: 'bar' }
// assume nextProps.value is { foo: 'bar' },
// but this reference is different to this.props.value
this.props.value !== nextProps.value; // true

When working with objects instead of values nextProps and this.props.value will be considered distinct references (unless we perform a deep comparison) and trigger a re-render, which at scale could be really expensive.

¹Unless you're simulating your own immutability, for what I trust Immutable.js better

Upvotes: 3

gaperton
gaperton

Reputation: 3826

You're not copying role, thus if one of your components taking the role as prop (if any) cannot take benefit of pure render optimization (overriding shouldComponentUpdate and detecting whenever props have been actually changed).

But since you can make a copy of the role without immutablejs, there is no any effective difference except that you have to type more (and thus having more opportunities to make a mistake). Which itself is a huge drawback reducing your productivity.

Upvotes: 0

Ashish Chaudhary
Ashish Chaudhary

Reputation: 798

From the setIn docs:

Returns a new Map having set value at this keyPath. If any keys in keyPath do not exist, a new immutable Map will be created at that key.

This is probably not what you are looking for since you may not want to insert a new member with the given role if it does not exist already. This comes down to whether you are able to control the userId argument passed in the function and verify whether it exists beforehand.

This solution is fine. You can replace it with update instead, if you want to.

Upvotes: -1

Related Questions