11

Let's say we have this code for a LWC:

<!-- helloExpressions.html -->
<template>
    <div class="slds-m-around_medium">
        <lightning-input name='firstName' label="First Name" onchange={handleChange}></lightning-input>
        <lightning-input name='lastName' label="Last Name" onchange={handleChange}></lightning-input>
        <p class="slds-m-top_medium">Uppercased Full Name: {uppercasedFullName}</p>
    </div>
</template>

and this is the JS file:

// helloExpressions.js
import { LightningElement, track } from 'lwc';

export default class HelloExpressions extends LightningElement {
    @track firstName = '';
    @track lastName = '';

    handleChange(event) {
        const field = event.target.name;
        if (field === 'firstName') {
            this.firstName = event.target.value;
        } else if (field === 'lastName') {
            this.lastName = event.target.value;
        }
    }

    get uppercasedFullName() {
        return `${this.firstName} ${this.lastName}`.toUpperCase();
    }
}

firstName and lastName have been decorated with @track. Now as per the documentation, decorating a property with @track makes it private and reactive, while to mark a property public and reactive, use @api.

So if I just change the decorator to @api for both these variables, it should work. I am referring these from the same component only. But it's not working.

UPDATE: 27th Feb -------------------- Somehow it's working today. I just changed the decorator of the variables to api.

import { LightningElement, api } from 'lwc';

export default class HelloExpressions extends LightningElement {
    @api firstName = '';
    @api lastName = '';

    handleChange(event) {
        const field = event.target.name;
        if (field === 'firstName') {
            this.firstName = event.target.value;
        } else if (field === 'lastName') {
            this.lastName = event.target.value;
        }
    }

    get uppercasedFullName() {
        return `${this.firstName} ${this.lastName}`.toUpperCase();
    }
}

So it's working.

1

3 Answers 3

17

It doesn't work because you don't have the right to mutate the value associated with a class field decorated with api. The LWC engine will only react for changes when the value is set by the component owner. This can be done by updating the property via the template or manually setting the value on the custom element.

While Aura leverages 2 ways data-binding, LWC encourages props down/events up pattern popularized by modern javascript framework. Allowing to mutation your properties from inside your component would go against this props down/events up principle.

8
  • Both @track and @api mark a property as reactive. If the property’s value changes, the component rerenders.
  • Tracked properties are private, where properties decorated with @api are public and can be set by another component.
  • @track is powerful, but remember, track a property only if you want the component to rerender when the property’s value changes. Don’t track every private property.
  • We can’t decorate a property with both @track and @api.

Source: https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.js_props_private_reactive

1
  • Please update the link. It's not a valid link any more. Thanks!
    – Bahman.A
    Commented Sep 16, 2021 at 19:55
1

@Track is referring to binding the value with the decorators and whenever the value of @track variable are changed then they reflect in the both sides. In case of using the @api, which refers to make the variable as a public property which will not result in binding the value of @api type of property to decorators.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .