Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose all @wire configurations on the element instance in non-prod modes #1902

Closed
kevinv11n opened this issue May 28, 2020 · 5 comments
Closed
Assignees

Comments

@kevinv11n
Copy link
Contributor

kevinv11n commented May 28, 2020

Is your feature request related to a problem? Please describe.

@wire'd properties are concise but don't provide insight into if and when a value is provisioned.

A customer recently shared this perspective:

I love how "wiring" Apex methods to properties reduces lines of code. But it makes debugging impossible. I have this js and see in the Apex logs that the method indeed is called but nothing ever reaches the Javascript property.

Consider this example LWC component:

import { LightningElement, wire} from 'lwc';
import myApexMethod from '@salesforce/apex/MyController.myApexMethod';

export default class MyComponent extends LightningElement {
  @wire(myApexMethod, { args })
  wiredProperty;
}
<template>
  <template if:true={this.wiredPropery.data}>
    {this.wiredPropery.data}
  </template>
</template> 

If this.wiredProperty.data isn't rendered, what was the cause?

  • Is the config args incorrect?
  • Was the provisioned value the empty string?
  • Did the wire service have an error?

Describe the solution you'd like

When in non-production mode, provide a developer with insight into:

  1. When a component's @wires provision a value (data or error)
  2. The resolved configuration that is responsible for a provisioned value
  3. When changes to resolved configuration are observed

This can be done by exposing the values on the element instance keyed from a known symbol. Continuing the example above, imagine running this code in the dev console after selecting the c-my-component element:

> $0[Symbol.for('@wire')]
{ 
  wiredProperty: {
    data: { ... }, // provisioned data, if any
    error: { ... }, // provisioned error, if any
    config: { ... } // resolved config values
  }
}

With wire reform getting the resolved configuration values is simple.

Describe alternatives you've considered

#1. Lifecycle Hook

Comparable to connectedCallback(), if you implement a (static?) function it is invoked when wires update: config, provision of value/error.

export default class MyComponent extends LightningElement {
  **wiredCallback**({wireName, config, value}) {
  }
}

This approach was rejected because a single codebase is used for dev and prod mode, which means this debugging logic contaminates the codebase.

#2 Metaconfig for a wire

Add an additional parameter to @wire which is a meta-config object.

export default class MyComponent extends LightningElement {
  @wire(getRecord, { ... }, **{ verbose: true }**)
  wiredProperty;
}

This approach was rejected because it restricts future evolution of @wire. It also suffers from placing the toggle for debug mode into the code whereas it is configured external to the component source code (eg on Lightning Platform it's via the Setup menu, in OSS it's a compiler/bundler flag).

#3 Callback on @wire

Add a third parameter arrow function to the @wire declaration that is invoked only in dev mode.

export default class MyComponent extends LightningElement {
  @wire(getRecord, {...config }, **(_debugOpts) => {...}**)
  wiredProperty;
}

This approach was rejected because it restricts future evolution of @wire. It also suffers from placing the toggle for debug mode into the code whereas it is configured external to the component source code (eg on Lightning Platform it's via the Setup menu, in OSS it's a compiler/bundler flag).

@pmdartus
Copy link
Member

pmdartus commented Jun 2, 2020

Thanks for raising this issue @kevinv11n.

The main concern that I have with a symbol attached to the host element is that it leaks internal details of the component on the host element. The wired properties have nothing to do with the custom element but with the component (those are 2 distinct objects in LWC). As a side effect, the parent component might also be able to observe in dev mode the child component wired properties, but this is less of an issue.

// From c-my-parent
this.querySelector('c-my-component')[Symbol.for('@wire')]

That being said, I think we should start exposing more information via the devtool to help developers debug LWC components and wired properties/methods. A preferable approach IMHO would be to define new APIs that a dedicated browser extension to hook into to observe and report the component state.

@caridy
Copy link
Contributor

caridy commented Jun 2, 2020

Good stuff! I'm very sympathetic with this. As for @pmdartus' concerns, I think we can mitigate that by not using Symbol.for, and instead, install one symbol per wired field, e.g.:

image

As you can see, by creating a new symbol every time, per instance, per wire, it reads very nice, and it is very hard for anyone to attempt to use this information before they realized it is a dev-mode only thing.

@caridy
Copy link
Contributor

caridy commented Jun 2, 2020

Btw, I believe this is an old issue for this somewhere. This was @philcalvin's first complain about LWC a long time ago... let's get this solved.

@salesforce salesforce deleted a comment from shesmer Nov 29, 2021
@khawkins
Copy link

The proposed facility is arguably a central component to the LWC development experience. @wires
are an area where any number of things can go wrong, and with varying consistency. Having access to more detailed error feedback early in the development cycle should both improve the quality of delivered components, and shorten the time to market for LWC developers.

@kevinv11n
Copy link
Contributor Author

Fixed in #3090. Thanks, @jodarove ! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants