1

I have the following declaration:

    constructor(props) {
    super(props);
    this.state = {
        productArray: [{
            barcode: '',
            name: ''
        }],
        numberOfRecords: '',
        return_code: '',
        return_string: ''
    };        
}

My hope is to reference the state fields like this:

this.state.productArray[0].barcode and this.state.productArray[1]

I also have a piece of code where I try to update the state. The code looks like this:

for (counter=0;counter<numberOfRecords;counter++) {

    currentComponent.setState({productArray[counter].barcode: tempData.barcode[counter]});                        
    currentComponent.setState({productArray[counter].name: tempData.name[counter]});
}

This does not compile and the error is pointing to the first setState command. The compiler is pointing at the [ in the reference to productArray[counter].barcode saying it expected a ','.

Am I defining the state correctly? If not, what would the proper syntax be? If yes, what is proper syntax to reference the individual state field pieces?

5
  • why is numberOfRecords an empty string and not a number? and how about just setting currentComponent.setState({ productArray: tempData })? Commented Aug 26, 2018 at 19:01
  • my bad on the default value of numberOfRecords. I should initialize it to zero. As for the data, I am picking off specific pieces of the tempData array so I did not feel it was necessary to save all the tempData data in the state. Commented Aug 26, 2018 at 19:05
  • thanks for the clarification, this wasn't apparent to me. Is numberOfRecords really state, or can it be easily computed? Like tempData.length for example? Commented Aug 26, 2018 at 19:12
  • excellent point. I can remove numberOfRecords from state and get it from tempData.length. Commented Aug 26, 2018 at 19:22
  • So far the great question of the day, keep learning. I have given without making shallow copies yourself and you can utilize the power of JS. Commented Aug 26, 2018 at 19:25

4 Answers 4

1

Ideally you only need a single call to setState something you can do is create a temporary variable where to store the computation such as

const { productArray, numberOfRecords } = this.state;
const newProducts = [ ... productArray ];
for( let counter = 0; counter < numberOfRecords; counter ) {
    const item = newProducts[ counter];
    newProducts[ counter] = { ...item, barcode: 'value' }, 
}

this.setState({ productArray: newProducts });

By using the spread operator ... you can create shallow copies of objects and arrays.

Sign up to request clarification or add additional context in comments.

Comments

0

you can't directly immutate the state please do it as

let tempvar = this.state.productArray;
for (counter=0;counter<numberOfRecords;counter++) {
tempvar[counter].barcode= newValue
}
this.setState({productArray:tempvar})

3 Comments

If that is the case, how would I be able to pass the state.productArray in an arrow function/map so I can render the data in state.productArray dynamically?
you can render it normally as you are not modifying the state their
you can do as this.state.productArray.map(index=><div>index.barcode</div>)
0

The recommended way to updated nested array of objects is to utilize the power of Object.assign. Keep in mind, that Object.assign will not perform a deep cloning, since it only copies property values,

this.setState({
    productArray:  Object.assign({}, this.state.productArray[0], {
      barcode: 'any value',
    })}, ()=>{
      console.log(this.state)
    }
  );

In your case, that's how you can achieve this with shorthand notation:

 for (var counter = 0; counter < 1; counter++) {
  this.setState({
    productArray:  Object.assign({}, this.state.productArray[counter], {
      barcode: tempData.barcode[counter],
      name: tempData.name[counter]
    })}, ()=>{
      console.log(this.state)
    }
  );
}

Comments

0

As for the data, I am picking off specific pieces of the tempData array

and

I can remove numberOfRecords from state and get it from tempData.length.

Ok, so productArray contains a subset of properties of the objects from tempData, and not a subset of items.

Then I'd not even bother trying to copy the values over and simply map the new values.

currentComponent.setState({ 
  productArray: tempData.map(item => {
    const {barcode, name} = item;
    return {barcode, name};
  })
});

//or in short

currentComponent.setState({ 
  productArray: tempData.map(({barcode, name}) => ({barcode, name}))
});

To answer your question; If you want to access and update some nested property, you should go with a update-function in setState() so ALL previous updates have been applied to this.state BEFORE your code tries to modify it.

Something like this:

currentComponent.setState((state) => {
  for(let i = 0; i<tempData.length; ++i){
    let from = tempData[i], to = state.productArray[i];

    to.name = from.name;
    to.barcode = from.barcode;
  }
  return state;
});

The downside/flaw of this approach is, that doesn't deal with the situations where tempData.length !== state.productArray.length.

1 Comment

Since I'm placing this code in componentWillMount() and I dont update the state anywhere else in the process, I dont think I need to worry about that instance.

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.