1

I'm creating a react/redux app to make characters for a role playing game and I want to be able to add and remove skills from the player state.

The way I'm currently removing skills looks like this:

const initState = {
    activeSkills: {},
    knowledgeSkills: {},
    skillPointsSpent: 0
}

const skillReducer = (state=initState, action) => {
    var {category, name} = action.parameter

    const actionsToTake = {
        ...//other actions

        DECREMENT_SKILL: () => {
            var newState;

            if(state[category][name].rating === 1) {
                newState = Object.assign(
                    {},
                    state,
                    {
                        skillPointsSpent: state.skillPointsSpent - 1
                    }
                );

                delete newState[category][name];
            }

            return newState
        },

        ...//other actions
    }

    return (actionsToTake[action.type] || actionsToTake.DEFAULT)();
}

The state I'm reducing from should look something like this, where I'm attempting to remove Archery. So category will be activeSkills and name will be Archery

state = {
    activeSkills: {
         Archery: {rating: 1, spec: 'Bow'}
    },
    knowledgeSkills: {},
    skillPointsSpent: 1
}

This is clearly the wrong way of doing it as it mutates my previous states. So what's an immutable way of removing properties from the state object?

dethstrobe
  • 545
  • 4
  • 13
  • It would help to know the organization of your `state` object. It's unclear what `category` and `name` represent and what their relationships are. – Brett Mar 15 '16 at 17:23
  • 1
    Possible duplicate of [Remove value from object without mutating it](http://stackoverflow.com/questions/33053310/remove-value-from-object-without-mutating-it) – flup Mar 15 '16 at 18:56
  • Thanks @flup, I think that makes sense. I think I have to copy the activeSkill inside the state object then delete the property. I'll be back if it works or doesn't work. – dethstrobe Mar 15 '16 at 19:10

1 Answers1

0

EDIT

Like the update in the link to @flup has linked to, the better way to handle this is with some object destructuring.

if(state[category][name].rating === 1) {
    const { [name]: discard, ...newCategory } = state[category];
    newState = {
        ...state,
        [category]: {
            ...newCategory
        },
        skillPointsSpent: state.skillPointsSpent - 1
    }
}

Original

Like the answer @flup linked to all I needed to do was make a copy of the more deeply nested object, then I could delete the property without mutating the previous states.

if(state[category][name].rating === 1) {
    newState = Object.assign(
        {},
        state,
        {
            [category] : Object.assign(
                {},
                state[category]
            ),
            skillPointsSpent: state.skillPointsSpent - 1
        }
    );

    delete newState[category][name];
}
Community
  • 1
  • 1
dethstrobe
  • 545
  • 4
  • 13