Example: Use a Built-in State Manager

This example is intended to show the simplest possible use of a built-in state manager. The important concepts are the state manager lifecycle, and understanding how to access response values.

In practice, if your usage pattern is this simple, use the wire service instead. To clearly illustrate essential concepts here, we’ve over-simplified the example code in this topic. See Best Practices for State Manager Design for more guidance on how built-in state managers are intended to be used.

Important

accountBrowserSimple.js
1import { LightningElement, wire } from 'lwc';
2import { gql, graphql } from "lightning/graphql";
3import smRecord from "lightning/stateManagerRecord";
4import NAME_FIELD from "@salesforce/schema/Account.Name";
5import OWNER_NAME_FIELD from "@salesforce/schema/Account.Owner.Name";
6import PHONE_FIELD from "@salesforce/schema/Account.Phone";
7import INDUSTRY_FIELD from "@salesforce/schema/Account.Industry";
8import { getFieldValue } from "lightning/uiRecordApi";
9
10export default class AccountBrowserSimple extends LightningElement {
11
12    // Create a state manager to retrieve account record data
13    // This is deliberately simple to illustrate concepts, not
14    // a recommended pattern.
15    myRecMgr = smRecord({
16        recordId: undefined,
17        fields: [ NAME_FIELD, INDUSTRY_FIELD ],
18        optionalFields: [PHONE_FIELD, OWNER_NAME_FIELD]
19    });
20
21    // UX: handle change to selected Account
22    handleMenuSelect(event) {
23        // Get the selected account record ID
24        const accountId = event.detail.value;
25        // Update the recordManager
26        this.myRecMgr.value.setRecordId(accountId);
27    }
28
29    // What's the state of the state manager
30    get accountAvailable() {
31        return this.myRecMgr.value.status === "loaded";
32    }
33
34    // This property provides the record data in the state manager
35    get accountData() {
36        if (this.accountAvailable) {
37            return this.myRecMgr.value.data;
38        }
39        return undefined;
40    }
41
42    // Record data fields for display
43    // This is deliberately tedious; don't do this!
44    get recName() {
45        return getFieldValue(this.accountData, NAME_FIELD);
46    }
47    get recOwner() {
48        return getFieldValue(this.accountData, OWNER_NAME_FIELD);
49    }
50    get recPhone() {
51        return getFieldValue(this.accountData, PHONE_FIELD);
52    }
53    get recIndustry() {
54        return getFieldValue(this.accountData, INDUSTRY_FIELD);
55    }
56
57    // UX: Show loading message in account selection menu while
58    //     gql query is running
59    get accountsLoading() {
60        if (this.results) return false;
61        return true;
62    }
63
64    // This GQL block is simply to get record IDs for some Accounts,
65    // for display in a menu in the component. It's purely for the UX,
66    // and has nothing to do with state managers
67    results; // Account IDs and Names, for the selection menu only
68    errors;
69    @wire(graphql, {
70        query: gql`
71            query AccountWithName {
72                uiapi {
73                    query {
74                        Account(first: 10) {
75                            edges {
76                                node {
77                                    Id
78                                    Name {
79                                        value
80                                    }
81                                }
82                            }
83                        }
84                    }
85                }
86            }
87        `,
88    })
89    graphqlQueryResult({ data, errors }) {
90        if (data) {
91            this.results = data.uiapi.query.Account.edges.map((edge) => edge.node);
92        }
93        this.errors = errors;
94    }
95
96    get stateDump() {
97        return JSON.stringify(this.myRecMgr.value, null, 2);
98    }
99}
accountBrowserSimple.html
1<template>
2    <lightning-card title="Example: Account Browser">
3
4        <!-- This section element is purely user interface, providing a
5            simple menu of accounts to view details for. -->
6        <section class="slds-p-around_small" title="Select an Account">
7            <template lwc:if={results}>
8                <lightning-button-menu
9                    alternative-text="Select Account"
10                    icon-name="utility:account"
11                    onselect={handleMenuSelect}
12                    loading-state-alternative-text="Loading accounts…"
13                    is-loading={accountsLoading}
14                >
15                    <template for:each={results} for:item="account">
16                        <lightning-menu-item
17                            label={account.Name.value}
18                            value={account.Id}
19                            key={account.Id}
20                            >
21                        </lightning-menu-item>
22                    </template>
23                </lightning-button-menu>
24            </template>
25        </section>
26
27        <!-- This section displays data using the `lightning/stateManagerRecord`
28            built-in state manager. -->
29        <section class="slds-p-around_small" title="Account Data">
30
31            <!-- Important: verify state manager data is ready/loaded -->
32            <template lwc:if={accountAvailable}>
33                <!-- This is deliberately hideous. You can do better. -->
34                Account name: {recName}<br/>
35                Industry: {recIndustry}<br/>
36                Phone: {recPhone}<br/>
37                Account Manager: {recOwner}<br/>
38            </template>
39
40            <!-- Debugging and inspection of state manager -->
41            <hr/>
42            <section class="slds-p-around_small">
43                <textarea rows="10" cols="40">{stateDump}</textarea>
44            </section>
45        </section>
46    </lightning-card>
47</template>