Reactive array of objects and “Use Lightning Web Security for Lightning Web Components”

arraylightning-web-componentslightning-web-securityobject

I have a component that iterates through a property that is an array of objects.

<template>
  <template for:each={widgets} for:item="widget">
    <p key="widget.name">
      <a onclick={clickedWidget} href="#" data-widget={widget.name}>{widget.name} ({widget.clicked})</a>
    </p>
  </template>
</template>
import { LightningElement } from 'lwc';

export default class Widgets extends LightningElement {
  widgets = [
    {
      name: 'Widget 1',
      clicked: false
    },
    {
      name: 'Widget 2',
      clicked: false
    }
  ];

  clickedWidget(event) {
    const widget = event.target.dataset.widget;
    const clickedWidget = this.widgets.find(el => el.name === widget); // Does not work!
    clickedWidget.clicked = true;
  }

}

Saw this question and answer. My package requires Use Lightning Web Security for Lightning Web Components to be enabled (one component uses the Carbon Charts library). I don't have the luxury of just turning it off.

New to LWC… should I be doing something differently?

Best Answer

Primitives are reactive, objects are not. However, you can just add @track to make an object reactive:

import { LightningElement, track } from 'lwc';

export default class Widgets extends LightningElement {
  @track widgets = [
    {
      name: 'Widget 1',
      clicked: false
    },
    {
      name: 'Widget 2',
      clicked: false
    }
  ];

  clickedWidget(event) {
    const widget = event.target.dataset.widget;
    const clickedWidget = this.widgets.find(el => el.name === widget);
    clickedWidget.clicked = true;
  }

}