> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bitfield.so/llms.txt
> Use this file to discover all available pages before exploring further.

# React surface for package data

> Read package-named data and send an action request from one React surface.

<div className="bf-article">
  <p className="bf-lead">
    Build the app-facing side of a Runtime Kit feature: one React surface reads named data, renders every state, and asks a named target to do work from a button.
  </p>

  Named data means Runtime Kit has already made a piece of Bitfield data available to this app surface. The component reads it. It does not create storage addresses or parse package files.

  ## When to use this

  Use this recipe when a screen needs both data and an action.

  | Good fit                                                              | Not this recipe                                  |
  | --------------------------------------------------------------------- | ------------------------------------------------ |
  | A welcome panel that reads copy and asks for a refresh.               | A package file with no UI yet.                   |
  | A search panel that reads prepared results and calls a search target. | A pure reference page for the hook signature.    |
  | A dashboard card that reads prepared metrics and triggers a target.   | A component that imports package files directly. |

  The point is the separation: the component owns UI state and user actions. Runtime Kit owns the public read/request line. The package owns the material served through that line.

  ## What you will build

  | Contract part   | Value                                                            |
  | --------------- | ---------------------------------------------------------------- |
  | React surface   | `WelcomePanel`                                                   |
  | Data name       | `welcome`                                                        |
  | Read call       | `useBitfieldData<WelcomeData>('welcome')`                        |
  | Target          | `product.search`                                                 |
  | Request payload | `{ reason: 'refresh-welcome-panel' }`                            |
  | UI states       | loading, error, empty, success, request success, request failure |
  | Public imports  | `@bitfield/runtime-kit`, `@bitfield/runtime-kit/react`           |

  ## Component

  ```tsx theme={null}
  import { sendRequestToBitfieldTarget } from '@bitfield/runtime-kit';
  import { useBitfieldData } from '@bitfield/runtime-kit/react';
  import { useState } from 'react';

  type WelcomeData = {
    headline: string;
    body: string;
  };

  export function WelcomePanel() {
    const welcome = useBitfieldData<WelcomeData>('welcome');
    const [requestMessage, setRequestMessage] = useState<string | null>(null);
    const [requestError, setRequestError] = useState<string | null>(null);

    async function refresh() {
      setRequestMessage(null);
      setRequestError(null);

      try {
        await sendRequestToBitfieldTarget({
          target: 'product.search',
          payload: { reason: 'refresh-welcome-panel' },
        });
        setRequestMessage('Refresh request sent.');
      } catch (error) {
        setRequestError(error instanceof Error ? error.message : 'Refresh request failed.');
      }
    }

    if (welcome.loading) return <section>Loading welcome panel.</section>;
    if (welcome.error) return <section>Could not load this panel.</section>;
    if (!welcome.data) return <section>No welcome copy yet.</section>;

    return (
      <section>
        <h2>{welcome.data.headline}</h2>
        <p>{welcome.data.body}</p>
        <button type="button" onClick={refresh}>
          Refresh
        </button>
        {requestError ? <p>{requestError}</p> : null}
        {requestMessage ? <p>{requestMessage}</p> : null}
      </section>
    );
  }
  ```

  ## Read path

  The read line is:

  ```tsx theme={null}
  const welcome = useBitfieldData<WelcomeData>('welcome');
  ```

  That line means:

  | Piece             | Meaning                                     |
  | ----------------- | ------------------------------------------- |
  | `WelcomeData`     | The shape this component expects to render. |
  | `'welcome'`       | Public data name for this surface.          |
  | `welcome.loading` | Runtime Kit is still preparing the value.   |
  | `welcome.error`   | Runtime Kit cannot provide the value.       |
  | `welcome.data`    | The current prepared value, or `null`.      |

  The selector is not a storage path. The component does not import the package record, file, or derived value that produced the data name.

  ## Request path

  The request line is:

  ```tsx theme={null}
  await sendRequestToBitfieldTarget({
    target: 'product.search',
    payload: { reason: 'refresh-welcome-panel' },
  });
  ```

  That line means:

  | Piece            | Meaning                                               |
  | ---------------- | ----------------------------------------------------- |
  | `target`         | Public callable name declared by package material.    |
  | `payload`        | App-owned request data Runtime Kit converts to bytes. |
  | `try/catch`      | UI handles request failure visibly.                   |
  | `requestMessage` | UI confirms the action happened.                      |

  The component does not import the target implementation.

  ## Verify the recipe

  Use this checklist before copying the surface into a real app:

  | Check           | Pass condition                                                                           |
  | --------------- | ---------------------------------------------------------------------------------------- |
  | Public imports  | Only imports Runtime Kit from `@bitfield/runtime-kit` and `@bitfield/runtime-kit/react`. |
  | Data name       | Reads `welcome` through `useBitfieldData(...)`.                                          |
  | Loading state   | Shows a visible loading message.                                                         |
  | Error state     | Shows a visible read error message.                                                      |
  | Empty state     | Shows a visible empty-state message instead of returning `null`.                         |
  | Success state   | Renders `headline` and `body`.                                                           |
  | Request path    | Calls `product.search` through `sendRequestToBitfieldTarget(...)`.                       |
  | Request failure | Catches request errors and renders a visible message.                                    |

  ### What should happen

  ```text theme={null}
  The surface can render before data is ready.
  The surface can show failed reads.
  The surface can show missing data.
  The surface can render real named data.
  The button can ask product.search for work without importing package implementation code.
  ```

  ## Bad version

  This version looks shorter, but it hides real states and crosses the boundary later:

  ```tsx theme={null}
  if (!welcome.data) return null;

  // Later:
  // import { runSearchDirectly } from '../packages/search-package/slot';
  ```

  That is how tangled apps start. The UI disappears when data is missing, and the button is one direct import away from bypassing Runtime Kit.

  ## Common failures

  | Symptom                                  | Cause                                                         | Fix                                                     |
  | ---------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------- |
  | Blank panel                              | Empty state returns `null`.                                   | Render a visible empty state.                           |
  | User sees no error                       | Component ignores `welcome.error` or request errors.          | Render read and request failures separately.            |
  | Button works only in local dev           | Component imported a target implementation directly.          | Call the public action name.                            |
  | Data shape crashes render                | Component assumed fields that the data name does not provide. | Align `WelcomeData` with the public data name contract. |
  | Component code creates storage addresses | The hook was treated like a database query.                   | Move back to the data name contract.                    |

  ## Review checklist

  The finished surface should answer:

  ```text theme={null}
  Data name:
  Action name:
  Request payload:
  Read states rendered:
  Request states rendered:
  Public imports used:
  Files changed:
  ```

  Reject the answer if it mentions package implementation imports, local state hand edits, hidden providers, or storage address construction inside the component.

  ## Why the component stays small

  The component has two jobs:

  * Read the prepared `welcome` data.
  * Ask `product.search` to do work.

  It does not import the record location, package byte path, target runner, or active package-set mount code.

  ## What changes when the package changes

  The package can add more records, ship more bytes, or replace the implementation for `product.search`. The component can stay the same as long as the public data shape and action name stay the same.

  ## Next

  Read [Read data in React](/runtime-kit/use-bitfield-data) for the hook contract.

  Read [Send a request](/runtime-kit/send-request) for payload conversion, reply bytes, cancellation, and request errors.

  Read [Runtime Kit API](/reference/runtime-kit-api) for exact `useBitfieldData(...)` and `sendRequestToBitfieldTarget(...)` contracts.

  Read [Package to screen](/runtime-kit/package-to-screen) for the full package-to-surface path.
</div>
