[SalesForce] LWC: @track binding won’t refresh component on value change

I have a component that picks up the value originally from the JS controller but won't refresh after I modify the value in the JS file.

Component:

<template>
    <div class={outterWrapperClass}/>
</template>

JS:

import { LightningElement, track } from 'lwc';

export default class SomeClass extends LightningElement {
    @track outterWrapperClass = 'outter-wrapper';

    connectedCallback() {
        window.addEventListener('scroll', function() {
            if (window.pageYOffset < 260) {
                this.outterWrapperClass = 'outter-wrapper';
            } else {
                this.outterWrapperClass = 'outter-wrapper-sidebar';
            }
            console.log('outer is ' + this.outterWrapperClass);
        });
    }
}

The value for this.outterWrapperClass is changing correctly in the console but the component's class value won't refresh. It's stuck on outter-wrapper. What am I doing wrong?

Best Answer

In the general sense, you'll want to have a separate function and bind that reference to the event handler:

connectedCallback() {
    window.addEventListener('scroll', this.scrollHandler.bind(this));
}
scrollHandler() {
    if (window.pageYOffset < 260) {
        this.outterWrapperClass = 'outter-wrapper';
    } else {
        this.outterWrapperClass = 'outter-wrapper-sidebar';
    }
    console.log('outer is ' + this.outterWrapperClass);
}

Function.prototype.bind will ensure that this refers to the component and not the window.

Related Topic