# Use `lightning/stateManager*` State Managers

Here are details of how to create and use built-in state managers.

## Creation and Lifecycle

Setting aside best practices, the basic process of using a built-in state manager is the same for all the state managers.

1. Create an instance of a state manager using its factory (default) function.
2. Wait for the state manager to retrieve the expected data, or return an error.
3. If there's an error, handle it.
4. After the data is loaded, do something with it.

:::important
In practice, if your usage pattern is this simple, use the wire service instead. To clearly illustrate the essential concepts here, we've over-simplified the example code in this topic. See [Best Practices for State Manager Design](/docs/platform/lwc/guide/reference-state-managers-design.md) for more guidance on how built-in state managers are intended to be used.
:::

### Factory Function

Create an instance of a built-in state manager using its factory (default) function. For example:

```javascript
// ...
import smRecord from "lightning/stateManagerRecord";
import NAME_FIELD from "@salesforce/schema/Account.Name";
import OWNER_NAME_FIELD from "@salesforce/schema/Account.Owner.Name";
import PHONE_FIELD from "@salesforce/schema/Account.Phone";
import INDUSTRY_FIELD from "@salesforce/schema/Account.Industry";

export default class Example extends LightningElement {

  @api theRecordId;

  // Create an instance of `lightning/stateManagerRecord`
  const myRecord = smRecord({
    recordId: theRecordId,
    fields: [NAME_FIELD, INDUSTRY_FIELD],
    optionalFields: [PHONE_FIELD, OWNER_NAME_FIELD]
  });

  // ...
}
```

After it’s created, check the status of and access data in the state manager through the [standard properties](#standard-properties).

### Configuration Functions

The factory function requires you to provide all required parameters at once. You can reconfigure a state manager instance with `setConfig()`, and provide difference values for all the same parameters. This function is available on all built-in state managers.

You can also update the configuration of a state manager instance by changing individual parameters as needed. Each parameter has its own `set` function.

For example, [`lightning/stateManagerObjectInfo`](/docs/platform/lwc/guide/reference-state-manager-object-info.md) has a single *setParameter* function, `setObjectApiName()`. [`lightning/stateManagerRelatedListRecords`](/docs/platform/lwc/guide/reference-state-manager-related-list-records.md) has several `set` functions, one for each parameter. The specific functions available are listed on the individual state manager reference topics.

## Standard Properties

All built-in state managers have the following properties.

### `status`

- "unconfigured" — the state manager doesn’t have sufficient configuration information to proceed.
- "loading" — the state manager is in the process of obtaining data.
- "loaded" — the state manager has loaded data and set the `data` property.
- "error" — there was an error loading the data. The `error` property contains additional information.

### `data`

When the state manager `status` property is "loaded", the `data` property is in a valid state, and can be used by consumers of the state manager. The form and structure of `data` depend on the specific state manager.

### `error`

When the state manager `status` property is "error", the `error` property is in a valid state, and contains details of the specific error. If there's a configuration error with the state manager itself, for example, missing or invalid parameters used in the factory function, `error` is usually a simple string. If the error is with the request or response, `error` can be a [`FetchResponse`](/docs/platform/lwc/guide/data-error.md). However, error handling is complex. See [Handle Errors in Lightning Data Service](/docs/platform/lwc/guide/data-error.md) for a thorough explanation.

## Refresh Action

State managers that expose data without a simple, concrete identity — such as a related list — expose an imperative `refresh` action. Call `refresh()` to force a state manager to fetch the latest data from the server.

These state managers expose `refresh()`:

- [`lightning/stateManagerRelatedListRecords`](/docs/platform/lwc/guide/reference-state-manager-related-list-records.md)

When you call `refresh()` on a state manager instance, it returns a `Promise<void>`.

```javascript
import { LightningElement, api } from "lwc";
import smRelatedListRecords from "lightning/stateManagerRelatedListRecords";
import CONTACT_NAME from "@salesforce/schema/Contact.Name";

export default class RelatedContacts extends LightningElement {
  @api recordId;

  contacts = smRelatedListRecords({
    parentRecordId: this.recordId,
    relatedListId: "Contacts",
    fields: [CONTACT_NAME],
  });

  async handleRefresh() {
    await this.contacts.value.refresh();
  }
}
```

### Refresh Behavior by Status

You can call `refresh()` only when the state manager's `status` is `loaded`. In that state, the state manager re-fetches data from the server. The `status` remains `loaded` during the refresh. The returned Promise resolves after the refreshed data is available on the state manager's `data` property.

For any other `status`, `refresh()` rejects the returned Promise without fetching data.

### Offline Behavior

Offline behavior for `refresh()` is undefined. Don't rely on any specific behavior when the client is offline.

## Reactivity

State managers are full participants in the reactivity system of the LWC Framework. However, there are a few nuances to understand how to ensure that your state managers are reactive in all the ways you expect.

### Standard Reactivity

Built-in state managers use the same underlying logic as wire adapters and react to the same changes as the wire adapters do. Specifically:

- Any record changes made by the Lightning Data Service (LDS) imperative `updateRecord` and `deleteRecord` functions
- Any record changes made via GraphQL mutations
- Changes detected as part of `notifyRecordUpdateAvailable` or `getRecordNotifyChange` processing
- Changes noticed while ingesting data from any other UI API call. For example, if you perform a `getRecordUi` call and LDS notices that an object info has changed then any affected values on instances of the object info and object infos state managers are updated.

### Reactivity by Changing the Configuration

The simplest kind of reactivity is triggering updates to a state manager by explicitly changing its configuration. See [Configuration Functions](#configuration-functions).

Components that reference values from a changed state manager automatically refresh as needed.

### Reactivity Using State Management Functions

To create a state manager that is reactive to values without requiring an explicit configuration change, wrap the dependent values in one of the state management functions, either `atom()` or `computed()`. You can do this when creating a state manager instance, using the factory function, or later by using one of the [configuration functions](#configuration-functions).

For example, here's a slightly modified excerpt from the [Nested State Manager Example](/docs/platform/lwc/guide/state-management-example-nested.md):

```javascript
import { defineState } from "@lwc/state";
import smRecord from "lightning/stateManagerRecord";
// ...
export default defineState(({ atom, computed, setAtom }, recordId, objectApiName) => {
    // This custom state manager's configuration is an `atom()`
    const config = atom({ recordId, objectApiName });

    // Changing the config uses the state management function `setAtom()`
    const setRecordId = (recordId) =>
      setAtom(config, { recordId, objectApiName: config.value.objectApiName });
    const setObjectApiName = (objectApiName) =>
      setAtom(config, { recordId: config.value.recordId, objectApiName });

    // ...
    // The custom state manager uses nested, built-in state managers.
    // When the built-in state manager instance is created, it passes in
    // the atom, `config`, so that `smRecord` will automatically be
    // updated anytime the config changes.
    const initialRecord = smRecord(
      computed([config], ({ recordId, objectApiName } = {}) => {
        // ...
        // IMPORTANT: This code is slightly revised for clarity;
        // See the original sample for complete syntax
```

The `stateManagerRecord` instance is part of the implementation of the custom state manager. It's reactive to changes in the custom state manager's configuration because the configuration `smRecord` receives in its factory function is an `atom()`.

### Non-reactive Events

State managers, including built-in state managers, react to updates that take place through Lightning Data Service (LDS). (Subject to implementation details explained in the preceding section.)

State managers can't react to changes that happen outside of LWC Framework reactivity mechanisms. For example, imperative Apex calls that change data.

**See Also**

- [Example: Use a Built-in State Manager](/docs/platform/lwc/guide/reference-state-managers-use-example.md)
- [Best Practices for State Manager Design](/docs/platform/lwc/guide/reference-state-managers-design.md)
