0

I have one @wire methods that are calling Apex methods to get results from objects.

After this information has been retrieved by @wire, I'd like to afterwards insert into different object based on what I get from the wire (in one call)

Is that possible to do that? and here is what I'm getting the error when I tried the approach. The error is not clear (at least to me) but after debugging my code I found where exactly the problem is and I will point out in the below code.

JS controller

@wire(fetchRecord, {recordId: '$recordId'})
wiredDetails(result) {
  if (result.data) {
    this.details = result.data; 
  } else if (result.error) {
    console.log(error);
    this.error = error;
  }
}

APEX:

@AuraEnabled(cacheable=true)
public static EmployeeController getRecords(String recordId) {
     Employee e = [SELECT .....];
     if (e != null) {
         insertNewRecords(e); //<<<<HERE is the ERROR I get
     }
}

private static void insertNewRecords(Employee__c e) {
      // inserting the record.....
}

Error:

LWCLuvioWireAdapter.emit()@https://dividend--dev.lightning.force.com/components/force/ldsBindings.js:342:16 emitAndSubscribe()@https://dividend--dev.lightning.force.com/components/force/ldsBindings.js:310:18

[LWC component's @wire target property or method threw an error during value provisioning. Original error: [error is not defined]]

Or any best practice or patterns should I follow in this situation?

1 Answer 1

2

When cacheable=true, the Apex method might not be called if a cached result exists. As such, Lightning requires any such method must be idempotent. DML and other operations are not idempotent, so are not allowed. In addition, you can't use wire when cacheable=false. Therefore, if you need to do this, you'll have to call Apex imperatively. From the wire handler.

Example

import { wire, api, LightningElement } from 'lwc';
import wiredMethod from '@salesforce/apex/method1';
import imperativeMethod from '@salesforce/apex/method2';

export default class MyClass extends LightningElement {
  @api recordId;
  details;
  @wire(wiredMethod, { recordId: '$recordId' })
  handler({data, error}) {
    if(data) {
      if(data.length) {
        this.details = data[0];
      } else {
        imperativeMethod({ recordId: this.recordId })
        .then(result => {this.details = result})
        .catch(error => this.showError(error))
      }
    }
    if(error) {
      this.showError(error)
    }
  }
}

Unfortunately, you will need two methods, and two calls, to answer your original question. It's a necessary limitation to avoid unexpected behavior, since wire methods may be called at any time, or even multiple times.

5
  • Do you have an example to show what you mean by just to get an idea
    – Nick
    Nov 6, 2021 at 23:30
  • 1
    @NickKahn I can edit one in for you, it's simple.
    – sfdcfox
    Nov 6, 2021 at 23:39
  • I was trying to avoid two calls but I guess I have not other options thanks for the sample code
    – Nick
    Nov 6, 2021 at 23:55
  • what is showError is that a js method to show any errors?
    – Nick
    Nov 7, 2021 at 0:12
  • @NickKahn Yeah, just a placeholder for whatever you want to do.
    – sfdcfox
    Nov 7, 2021 at 1:18

You must log in to answer this question.

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