Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update single value inside specific array item in redux

People also ask

How do you update an element in an array?

To update all the elements of an array, call the forEach() method on the array, passing it a function. The function gets called for each element in the array and allows us to update the array's values. Copied! const arr = ['zero', 'one', 'two']; arr.

How do you update the array of object state in react?

To update an array of objects state in React: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met. Update the properties of the object that matches the condition.

How do I update Redux value?

First, we will find the index of the item in the array using findIndex() . Then we make a copy of the todos array from the state. Then we can change the value in the new array using the index value we got from findIndex() . Lastly, in the return, we reassign todos to that new array.

How do you update a component in Redux state change?

The way you have it written, the state won't update unless you explicitly update it using setState() (most likely in the componentWillReceiveProps() method). When you use mapStateToProps() with the Redux connect() HOC, you are mapping your Redux state to your component through its props, so in your case this.


You can use map. Here is an example implementation:

case 'SOME_ACTION':
   return { 
       ...state, 
       contents: state.contents.map(
           (content, i) => i === 1 ? {...content, text: action.payload}
                                   : content
       )
    }

You could use the React Immutability helpers

import update from 'react-addons-update';

// ...    

case 'SOME_ACTION':
  return update(state, { 
    contents: { 
      1: {
        text: {$set: action.payload}
      }
    }
  });

Although I would imagine you'd probably be doing something more like this?

case 'SOME_ACTION':
  return update(state, { 
    contents: { 
      [action.id]: {
        text: {$set: action.payload}
      }
    }
  });

Very late to the party but here is a generic solution that works with every index value.

  1. You create and spread a new array from the old array up to the index you want to change.

  2. Add the data you want.

  3. Create and spread a new array from the index you wanted to change to the end of the array

let index=1;// probably action.payload.id
case 'SOME_ACTION':
   return { 
       ...state, 
       contents: [
          ...state.contents.slice(0,index),
          {title: "some other title", text: "some other text"},
         ...state.contents.slice(index+1)
         ]
    }

Update:

I have made a small module to simplify the code, so you just need to call a function:

case 'SOME_ACTION':
   return {
       ...state,
       contents: insertIntoArray(state.contents,index, {title: "some title", text: "some text"})
    }

For more examples, take a look at the repository

function signature:

insertIntoArray(originalArray,insertionIndex,newData)

Edit: There is also Immer.js library which works with all kinds of values, and they can also be deeply nested.


You don't have to do everything in one line:

case 'SOME_ACTION': {
  const newState = { ...state };
  newState.contents = 
    [
      newState.contents[0],
      {title: newState.contents[1].title, text: action.payload}
    ];
  return newState
};

I believe when you need this kinds of operations on your Redux state the spread operator is your friend and this principal applies for all children.

Let's pretend this is your state:

const state = {
    houses: {
        gryffindor: {
          points: 15
        },
        ravenclaw: {
          points: 18
        },
        hufflepuff: {
          points: 7
        },
        slytherin: {
          points: 5
        }
    }
}

And you want to add 3 points to Ravenclaw

const key = "ravenclaw";
  return {
    ...state, // copy state
    houses: {
      ...state.houses, // copy houses
      [key]: {  // update one specific house (using Computed Property syntax)
        ...state.houses[key],  // copy that specific house's properties
        points: state.houses[key].points + 3   // update its `points` property
      }
    }
  }

By using the spread operator you can update only the new state leaving everything else intact.

Example taken from this amazing article, you can find almost every possible option with great examples.


In my case I did something like this, based on Luis's answer:

// ...State object...
userInfo = {
name: '...',
...
}

// ...Reducer's code...
case CHANGED_INFO:
return {
  ...state,
  userInfo: {
    ...state.userInfo,
    // I'm sending the arguments like this: changeInfo({ id: e.target.id, value: e.target.value }) and use them as below in reducer!
    [action.data.id]: action.data.value,
  },
};