LWC wire function wont acknowledge the controller property

lightninglightning-web-components

Im missing something obvious while trying to add an index property to an array. Can anyone point to why this would be happening? Im gonna cringe when someone points this out, I just know it but Im stuck!

At render I get with this LWC component's @wire target property or method threw an error during value provisioning. Original error:
[Cannot read properties of undefined (reading 'settingsWrapper')]

export default class Foo extends LightningElement {
    
    settingsWrapper;
    
    @wire (getEpiStatusSettings) 
    settings({ error, data}){
        if(data){
            this.settingsWrapper = [];
            data.forEach(function(elem,i){
                var clone = Object.assign({}, elem); // this should give me an extensible object
                clone.index = i; // want to drop index in here for use later
                this.settingsWrapper.push(clone); // seems I cant push to an undefined object?
            });
        }
        
    };
}  

Any pointers would be most appreciated!

Best Answer

Consider using arrow function => instead of function itself.

In regular functions the this keyword represented the object (function, object and function are the same in js) that called the function.

With arrow functions the this keyword always represents the object that defined the arrow function:

export default class Foo extends LightningElement {
    
    settingsWrapper;
    
    @wire (getEpiStatusSettings) 
    settings({ error, data}){
        if(data){
            this.settingsWrapper = [];
            data.forEach((elem,i) => {
                var clone = Object.assign({}, elem); // this should give me an extensible object
                clone.index = i; // want to drop index in here for use later
                this.settingsWrapper.push(clone); // seems I cant push to an undefined object?
            });
        }
        
    };
}

There is a good trailhead module Understand JavaScript Functions related to this topic.


by the way, also consider using map instead of forEach

export default class Foo extends LightningElement {
    
    settingsWrapper;
    
    @wire (getEpiStatusSettings) 
    settings({ error, data}){
        if(data){
            this.settingsWrapper = data.map((elem,index) => ({...elem, index}));
        }   
    };
}