43

In React's this.state I have a property called formErrors containing the following dynamic array of objects.

[
  {fieldName: 'title', valid: false}, 
  {fieldName: 'description', valid: true},
  {fieldName: 'cityId', valid: false},
  {fieldName: 'hostDescription', valid: false},
]

Let's say I would need to update state's object having the fieldName cityId to the valid value of true.

What's the easiest or most common way to solve this?

I'm OK to use any of the libraries immutability-helper, immutable-js etc or ES6. I've tried and googled this for over 4 hours, and still cannot wrap my head around it. Would be extremely grateful for some help.

3
  • Did you try iterating over the array, and if fieldName === 'cityId' then set valid to true? This seems very straightforward.... what am I missing? It might help if you posted some of the things you've tried. Commented May 4, 2017 at 20:47
  • I am also thinking the same as @alexanderbird, so do you have a specific performance requirement? Commented May 4, 2017 at 20:48
  • My issue is about dealing with immutable data. Commented May 4, 2017 at 20:49

5 Answers 5

45

You can use map to iterate the data and check for the fieldName, if fieldName is cityId then you need to change the value and return a new object otherwise just return the same object.

Write it like this:

var data = [
    {fieldName: 'title', valid: false}, 
    {fieldName: 'description', valid: true},
    {fieldName: 'cityId', valid: false},
    {fieldName: 'hostDescription', valid: false},
]

var newData = data.map(el => {
                  if(el.fieldName == 'cityId')
                     return Object.assign({}, el, {valid:true})
                  return el
              });

this.setState({ data: newData }); 
Sign up to request clarification or add additional context in comments.

2 Comments

Although this would iterate over the entire array regardless of when the item to be updated appears.
You could set a simple flag in that case to optimize and avoid iterating through the whole array. Also you could replace Object.assign with spread operator like return {...el,valid:true}
14

Here is a sample example - ES6

The left is the code, and the right is the output

enter image description here

Here is the code below

const data = [
    { fieldName: 'title', valid: false }, 
    { fieldName: 'description', valid: true },
    { fieldName: 'cityId', valid: false }, // old data
    { fieldName: 'hostDescription', valid: false },
]

const newData = data.map(obj => {
  if(obj.fieldName === 'cityId') // check if fieldName equals to cityId
     return {
       ...obj,
       valid: true,
       description: 'You can also add more values here' // Example of data extra fields
     }
  return obj
});

const result = { data: newData }; 

console.log(result);

this.setState({ data: newData });

Hope this helps, Happy Coding!

2 Comments

What is the name of the program you are using in your screenshot?
@Derek I think this is one of the popular tools that can achieve the same thing: getsharex.com
2

How about immutability-helper? Works very well. You're looking for the $merge command I think.

@FellowStranger: I have one (and only one) section of my redux state that is an array of objects. I use the index in the reducer to update the correct entry:

case EMIT_DATA_TYPE_SELECT_CHANGE:
  return state.map( (sigmap, index) => {
    if ( index !== action.payload.index ) {
      return sigmap;
    } else {
      return update(sigmap, {$merge: {
        data_type: action.payload.value
      }})
    }
})

Frankly, this is kind of greasy, and I intend to change that part of my state object, but it does work... It doesn't sound like you're using redux but the tactic should be similar.

4 Comments

The problem is that I've tried it but cannot understand their syntax how to replace a value in array of objects :/
simply follow the example here: github.com/kolodny/immutability-helper#nested-collections. You want to update the valid parameter of the object at index 2, so something like update(formErrors, {2: {valid: {$set: true}}})
or update(formErrors, {2: {$merge: {valid: true}}})
@FellowStranger definitely futz with immutability-helper's update function. Very, very useful. It does take a while to learn the syntax....
1

Instead of storing your values in an array, I strongly suggest using an object instead so you can easily specify which element you want to update. In the example below the key is the fieldName but it can be any unique identifier:

var fields = {
    title: {
        valid: false
    },
    description: {
        valid: true
    }
}

then you can use immutability-helper's update function:

var newFields = update(fields, {title: {valid: {$set: true}}})

Comments

0

With ECMAScript 2023 we got the with method that could be the right fit for this purpose:

const data = [
  {fieldName: 'title', valid: false}, 
  {fieldName: 'description', valid: true},
  {fieldName: 'cityId', valid: false},
  {fieldName: 'hostDescription', valid: false},
];

const i = data.findIndex(({fieldName}) => fieldName === 'cityId');
const newData = data.with(i, {...data[i], valid: true });

console.log(newData);

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.