简体   繁体   中英

reactJS state array of objects - how do I reference the state array object in setState()

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?

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.

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})

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)
    }
  );
}

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM