Photo by Hans-Peter Gauster on Unsplash

How to Update a Single Key/Value Pair in Your Redux State

It’s easier than you think.

I have an array of television program objects. The objects contain the name, network, and image for the program. On each item in the array, I have a heart button. The heart allows the user to add the program to a watchlist. Each program is created with a watchlist attribute which is set to false. Clicking the button will toggle the watchlist attribute to true or false.

TV List Index page
The heart/toggle button on “Jessica Jones” should have been clicked from day one if I’m being honest.

THE PROBLEM

I was making a patch fetch request in my React/Redux app. I was able to get it to update in my database, but could not figure out how to reflect this change in my reducer so it could update the state and rerender the page.

Thankfully, I learned about how to make a copy of my array of program objects, which allowed me to make the changes I needed without suffering any funky consequences on the DOM. Hat tip to coder extraordinaire Bruno Garcia Gonzalez for showing me.

THE SOLUTION

Here is my lonely case statement..

case ‘TOGGLE_WATCHLIST’:
return {}

Since my reducer contains state = {programs : [] } the first thing I need to do is make a copy of the programs array. In Redux, that takes a bit of planning. I am going to use an approach called making a “deep copy”. Here, I create a copy of my current array by first turning it into a string.

case ‘TOGGLE_WATCHLIST’:
let stringifiedPrograms = JSON.stringify(state.programs)
return {}

After creating stringifiedPrograms, I then use JSON.parse to undo what I just did by turning the it back into a hash. This process returns a brand new array of objects.

case ‘TOGGLE_WATCHLIST’:
let stringifiedPrograms = JSON.stringify(state.programs)
    let copyOfPrograms = JSON.parse(stringifiedPrograms)
return {}

I then take copyOfPrograms and find the specific program that needs to be updated. The easiest way to do that is by its id. I use the .find method because it returns the first item that matches the condition I set in the arrow function.

case ‘TOGGLE_WATCHLIST’:
let stringifiedPrograms = JSON.stringify(state.programs)
    let copyOfPrograms = JSON.parse(stringifiedPrograms)
    let programToBeToggled = copyOfPrograms.find(program => program.id === action.id)
return {}

The toggling is isolated to a specific program which I want to add to a watchlist. After isolating that program, I update the value of watchlist. It is a boolean, so I want to set it to the opposite of what the value is currently.

case ‘TOGGLE_WATCHLIST’:
let stringifiedPrograms = JSON.stringify(state.programs)
    let copyOfPrograms = JSON.parse(stringifiedPrograms)
    let programToBeToggled = copyOfPrograms.find(program =>      program.id === action.id)
    programToBeToggled.watchlist = !action.watchlist
return {}

After that is complete, all that is left is to return my updated programs array with the program key set to our copyOfPrograms. One of the neatest things to note here is that updating my programToBeToggled watchlist value still updates it in the copyOfPrograms array.

case ‘TOGGLE_WATCHLIST’:
let stringifiedPrograms = JSON.stringify(state.programs)
    let copyOfPrograms = JSON.parse(stringifiedPrograms)
    let programToBeToggled = copyOfPrograms.find(program =>      program.id === action.id)
    programToBeToggled.watchlist = !action.watchlist
return {...state, programs: copyOfPrograms}

Checking the DOM, I can see that the item is now toggled.

VICTORY IS MINE!

I hope this cloning tip helps you in your future Reduxing. Happy coding!