Cross-Cutting Concerns in Lightning Web Components (Solved)
Exploring how to use the @wire decorator and @lwc/wire-service library to solve cross-cutting concerns with Lighting Web Components.

The examples in this article are available for download.
Prerequisites
This article assumes that the reader is already developing with Lightning Web Components; see the article Lightning Web Components (The Open Source Version).
It is also helpful to have read Lightning Web Components and Apollo Client; problems surfaced in that article were the impetus for writing this article.
To follow along, the required development tools are:
- Node.js (examples developed using 10.16.0 LTS)
- A text editor; recommend Visual Studio Code
Motivation
Much like other JavaScript component frameworks, e.g., React, one will find patterns of repeated code between Lighting Web Components; these patterns are referred to as cross-cutting concerns.
Over the years with React, there have been a number of approaches to address, i.e., creating generalized code, cross-cutting concerns:
- Mixins: This approach has been long (like 3 years) been retired
- Higher Order Components (HOCs): A function that takes a component and returns a new component.
- Render Props: A technique for sharing code between React components using a prop whose value is a function
- Hooks: A relatively recent, Winter 2019, pattern for addressing cross-cutting concerns
Looking through the Lighting Web Component documentation, there is nothing specifically addressing cross-cutting concerns (as of the writing of this article). While there is a section on sharing JavaScript code, it does not provide an approach to integrate that code with Lightning Web Components.
A Concrete Cross-Cutting Concern with Apollo Client
In a separate article, Lightning Web Components and Apollo Client, we walk through an example of using Apollo Client with Lightning Web Components.
In the conclusion of that article, we observe that there is fair amount of boilerplate code that would become repetitive were we to add additional queries and mutations.
For example there is the Todos component, a component that executes a GraphQL query and displays the results. Much of this code, up to 50 lines, would be repeated in another such query component.
Also there is the TodosCreate component, a component that takes form input and executes a GraphQL mutation. While less repetitive than the Todos component, some of this code would be repeated in another such mutation component.
With Apollo Client with React, there are two Render Props components, Query and Mutation provided in the react-apollo library, that address each of these cross-cutting concerns respectively.
If you have not guessed it yet, we will conclude this article with a similar solution for Lightning Web Components.
Problem Solving Mode
Having been thinking about Lightning Web Components for several weeks, I have toyed with two approaches to addressing cross-cutting concerns:
- Decorators: The problem here is that lwc-create-app does not support user created decorators; citing that they are not yet part of JavaScript standards
- Subclass Factories: The problem here is that there are not a lot of concrete examples using this pattern; makes me nervous
Luckily, however, a Lightning Web Component contributor reached out to me through a related issue and told me about the LWC @wire decorator and the @lwc/wire-service library.
He also mentioned that there is a growing list of examples provided in the the lwc-recipes-oss repository; including a simple example using the LWC @wire decorator and the @lwc/wire-service library.
@wire
While the @wire decorator is explained in context of the Salesforce LWC implementation, it is not documented for the open-source version.
The solution is described, albeit a bit tersely, in separate documentation for the @lwc/wire-service library.
Here we will explain the approach through a simple example using the @wire decorator and the @lwc/wire-service library.
Starting from an application created using lwc-create-app, we install the @lwc/wire-service library:
npm install @lwc/wire-service
Early in the application startup, we need to initialize the feature; we do so by updating src/index.js:
Before we dive into creating a wire adapter, let us see how we use them. The following HelloWorld LWC will first display an empty div and three seconds later will fill it with “Hello World!”; how wonderfully boring. The implementation; src/modules/my/helloWorld/hellWorld.html and helloWorld.js:
Observations:
- The @wire decorator takes two parameters: adapterId and adapterConfig
- adapterId: Refers to the identity of a wire adapter; in this case the helloWorldWire adapter that we will build next
- adapterConfig: An optional parameter, of type object, that defines wire adapter-specific configuration; in this case passing in the text World (used in constructing the output)
- The @wire decorator automatically makes the property it decorates into a reactive property; much like the @track decorator does. In this case, after three seconds the helloData property us updated and thus the component re-renders
- The numerous console log output are in place to surface how wire adapter events integrate with the LWC component lifecycle (in the next section)
@lwc/wire-service
Now let us implement the helloWorldWire wire adapter; src/modules/my/helloWorldWire/hellWorldWire.html and helloWorldWire.js:
Observations:
- While the HTML file is not used, it was required to get the project to compile
- When a wire adapter is used in a component, there are four events (linked to the component’s lifecycle events) where we can inject functionality; register, config, connect, and disconnect. It is important to note that these events happen independently for each instance of a wire adapter being used in a component
- To help visualize the wire adapter’s events along side the component’s lifecycle events, here is the console log output (and explanation) for this example when the component is added to the DOM:
- CONSTRUCTED
Component’s constructor - HELLO WORLD WIRE REGISTER
register: This wire adapter event is technically a function call. In this example, we initialize two private variables (connected and world) and setup listeners for the remaining three events (config, connect, and disconnect) - HELLO WORLD WIRE CONFIG
config: In this wire adapter example, the callback sets the private world variable to the provided configuration value. While not relevant in this example, the config event can be triggered later when the wire adapter is provided an updated configuration; apparently one can pass a reactive property as part of the configuration (mind blowing) - HELLO WORLD WIRE CONNECT
connect: In this wire adapter example, the callback sets a three second pause before running additional code (below) - CONNECTED
Component’s connected event - RENDERED
Component’s rendered event (the component displays the empty div) - HELLO WORLD WIRE DISPATCH EVENT
After three seconds, the connect callback resumes and dispatches a ValueChanged event using the private variable world - RENDERED
Because the @wire decorator makes the property reactive, the component re-renders (the component displays Hello World! in the div)
And when the component is removed from the DOM:
- HELLO WORLD WIRE DISCONNECT
disconnect: In this example, we remove the event listeners for the config, connect, and disconnect events - DISCONNECTED
Component’s disconnect event
Apollo Client and @wire and @lwc/wire-service
Now that we have demonstrated a pattern for handling LWC cross-cutting concerns, we can refactor the Apollo Client example using it.
We first demonstrate how to use the queryWire adapter:
src/modules/my/todos/todos.html
Observations:
- The queryWire adapter is modeled after the react-apollo Query component
and then the mutationWire adapter:
src/modules/my/todosCreate/todosCreate.html
src/modules/my/todosCreate/todosCreate.js
Observations:
- The mutationWire adapter is modeled after the react-apollo Mutation component
And here are the implementations for both of these adapters:
src/modules/my/queryWire/queryWire.html
src/modules/my/queryWire/queryWire.js
src/modules/my/mutationWire/mutationWire.html
src/modules/my/mutationWire/mutationWire.js
Observations:
- While complicated at first glance, these implementations are straightforward implementations built using the pattern provided in the helloWorldWire adapter and the example provided in Lightning Web Components and Apollo Client
Conclusion
While a bit more complicated that the similar patterns in React (esp. Hooks), we have demonstrated a real-world example of solving cross-cutting concerns in Lightning Web Components using @wire and @lwc/wire-service.