Loading Stateful components

Stateful components like API client need data on their first rendering. For example, identifying 404 NotFound with some object needs load completion.

If a framework provides lifecycle callbacks, you can utilize an initial hook. CustomeElements API for WebComponents provides connectedCallback() and Lit has one. If you want to wait API call, async connectedCallback() can simplify the workflow.

Antipattern: Complicated with Hooks

Historically, React 16.8 introduced its Hooks API for functional components. It does not have dedicated init hooks, nor async keyword.
While React FC w/Hooks is still major composition in 2022, functional components are not suitable for stateful components.

Asynchronous nautre of API call doesn’t match synchronous rendering interface.

Staged await

Web applications often request multiple APIs.
Each component needs to wait a set of several API calls.

Singleton Promises design pattern provides a practical way to await API calls.
And more, multiple singletons can be connected in a staged way:

class ApiClient {

  constructor() {
    this._stage1 = null;_
    this._stage2 = null;_
  }

  async stage1() {
    if(!this._stage1)
      this._stage1 = first_load();

    return this._stage1;
  }

  async stage2() {
    if(!this._stage2)
      this._stage2 = second_load();

    return this._stage2;
  }

  async first_load() {
    await 1st_api_call();
    await 2nd_api_call();
  }

  async second_load() {
    await this.stage1();
    await 3rd_api_call();
  }
}

If apiclient.second_load() called, 1st_api_call(), 2nd_api_call() and 3rd_api_call() will be executed in a row.
Then, await apiclient.stage2() can await these 3 api calls.

With this pattern, components can await part of API completion like following:

import { LitElement } from "lit";
import { CLIENT } from './some-client-provider.js';

class SampleComponent extends LitElement {
  async connectedCallback() {
    await CLIENT.stage1();
    super.connectedCallback();
  }
}

Complicated apps need to load series of data, which can be accomplished with awaiting full stage of API calls.
Implementing staged singleton promises, components can await part of APIs before rendering.

Resolved promise will respond immediately, therefore it doesn’t await anything after load completion.

Additional data in the later stage can be obtained via normal reactive framework.

⁋ Dec 20, 2022↻ Nov 7, 2024
中馬崇尋
Chuma Takahiro