The GraphQL query() method in the Data SDK includes several parameters.
import { createDataSDK, gql } from "@salesforce/platform-sdk/data";
const dataSdk = await createDataSDK();
const result = await dataSdk.graphql?.query<ResponseType, VariablesType>({
query: QUERY_STRING,
variables: { ... },
operationName?: "...",
cacheControl?: "no-cache" | "only-if-cached" | { type: "max-age", maxAge: 60 }
});
const QUERY_STRING = gql`
query MyQuery {
uiapi {
...
}
}
`;
graphql.query<T, V = Record<string, unknown>>(options: QueryOptions<V>)
Runs a GraphQL query with reactive capabilities.
Parameters
| Parameter | Type | Description |
|---|---|---|
query |
string |
The GraphQL query operation string, which accepts an inline gql template tag or an external .graphql file. |
variables? |
V, defaults to Record<string, unknown> |
Optional key-value map of GraphQL variables referenced by the query. |
operationName? |
string |
Optional operation name for multi-operation documents. |
cacheControl? |
CacheControl |
Optional cache control settings for the GraphQL request. |
UI API Query Structure
All GraphQL queries follow this UI API structure.
query {
uiapi {
query {
<ObjectName>(
first: Int # pagination limit
after: String # pagination cursor
where: <Object>_Filter
orderBy: <Object>_OrderBy
) {
edges {
node {
Id
<FieldName> { value }
}
}
}
}
}
}
For more information, see Query Objects in the GraphQL API Developer Guide.
Returns
Promise<QueryResult<T>>
The return type of dataSdk.graphql?.query(), which resolves to the typed GraphQL response payload.
interface QueryResult<T> {
data: T | undefined;
errors?: GraphQLError[];
subscribe(cb: QuerySubscriber<T>): Unsubscribe;
refresh(): Promise<void>;
}
GraphQL record queries return this response structure.
interface UIAPIQueryResponse {
uiapi: {
query: {
[ObjectName: string]: {
edges?: Array<{
node?: {
Id: string;
// Every field is a { value, displayValue } envelope, not a bare scalar.
// - value: raw value — use for logic and for writing back to the server
// - displayValue: locale-formatted string — use for rendering in the UI
[FieldName: string]?: { value?: FieldType | null; displayValue?: string | null } | null;
} | null;
} | null> | null;
} | null;
};
};
}
} | null;
} | null> | null;
} | null;
};
};
}
Subscribe to Query Updates
Query results from graphql.query() are reactive and support real-time updates through subscriptions, which you can use to update your UI automatically when data changes.
The subscribe() method listens for updates to a query result. Subscribers are notified when the data changes due to cache updates or explicit refreshes.
const result = await dataSdk.graphql?.query<AccountData>({
query: GET_ACCOUNT,
variables: { id: accountId },
});
// Subscribe to updates
const unsubscribe = result.subscribe((snapshot) => {
console.log("Updated data:", snapshot.data);
if (snapshot.errors) {
console.warn("Errors:", snapshot.errors);
}
// Update your UI here
});
// Clean up when done
unsubscribe();
Refresh Query Data
Use the refresh() method to manually re-fetch data, bypassing the cache.
const result = await dataSdk.graphql?.query<AccountData>({
query: GET_ACCOUNT,
variables: { id: accountId },
});
// Subscribe to updates
result.subscribe((snapshot) => {
// UI update logic
setAccount(snapshot.data);
});
// Later, refresh the data (e.g., on button click)
async function handleRefresh() {
await result.refresh(); // Notify subscribers
}
Example: Query Records from a React App
Here's an example on how to query records. The example uses the useState and useEffect React hooks to manage the component state and respond to data changes.
/**
* List Rendering with Salesforce Records
*
* Fetches Accounts via UIAPI GraphQL and renders them using .map().
* Each item needs a stable key prop; here we use the record Id.
*
* LWC equivalent: list rendering uses for:each / lwc:for directives on
* template elements with a key attribute. React uses .map() in JSX with
* a key prop.
*
* @see ParentToChild — passing data from parent to child components via props
*/
import { useEffect, useState } from 'react';
import { createDataSDK, gql } from '@salesforce/platform-sdk';
const QUERY = gql`
query AccountList {
uiapi {
query {
Account(first: 6, orderBy: { Name: { order: ASC } }) {
edges {
node {
Id
Name @optional {
value
}
Industry @optional {
value
}
}
}
}
}
}
}
`;
interface QueryResponse {
uiapi: {
query: {
Account: {
edges: Array<{
node: {
Id: string;
Name: { value: string | null };
Industry: { value: string | null };
};
}>;
};
};
};
}
interface AccountFields {
id: string;
name: string;
industry: string | null;
}
export default function ListOfAccounts() {
const [accounts, setAccounts] = useState<AccountFields[]>();
const [error, setError] = useState<string>();
useEffect(() => {
const fetchAccounts = async () => {
const sdk = await createDataSDK();
const result = await sdk.graphql?.query<QueryResponse>({ query: QUERY });
if (result?.errors?.length) {
throw new Error(
result.errors.map((e: { message: string }) => e.message).join('; ')
);
}
const edges = result?.data?.uiapi?.query?.Account?.edges ?? [];
setAccounts(
edges
.map(edge => edge?.node)
.filter(Boolean)
.map(node => ({
id: node.Id,
name: node.Name?.value ?? 'Unknown',
industry: node.Industry?.value ?? null,
}))
);
};
fetchAccounts().catch(err => {
setError(err instanceof Error ? err.message : 'Request failed');
});
}, []);
if (error) return <p className="text-destructive">{error}</p>;
if (!accounts) return <p className="text-sm">Loading…</p>;
return (
<ul>
{/* .map() replaces LWC's for:each directive. The key must be stable — record Id is ideal. */}
{accounts.map(account => (
<li
key={account.id}
className="py-2 -mx-2 px-2 rounded-md transition-colors hover:bg-accent/50"
>
<p className="text-sm">{account.name}</p>
{account.industry && (
<p className="text-xs text-muted-foreground">{account.industry}</p>
)}
</li>
))}
</ul>
);
}
tip: For more examples, see the Multi-framework recipes repo.
Example: Successful GraphQL Query Response
A successful query response includes record data in the node object.
{
"data": {
"uiapi": {
"query": {
"Account": {
"edges": [
{
"node": {
"Id": "001xx000003DHP0AAO",
"Name": { "value": "Acme Corp" },
"Industry": { "value": "Technology" }
}
}
],
"pageInfo": {
"hasNextPage": false,
"endCursor": null
}
}
}
}
}
}
Example: Partial Success Response
A partially successful query response includes errors and some data.
{
"data": {
"uiapi": {
"query": {
"Account": {
"edges": [
{
"node": {
"Id": "001xx000003DHP0AAO",
"Name": { "value": "Acme Corp" }
}
}
]
}
}
}
},
"errors": [
{
"message": "Insufficient access on field AnnualRevenue",
"path": ["uiapi", "query", "Account", "edges", 0, "node", "AnnualRevenue"]
}
]
}
See Also
- Error Handling in Data SDK
- Cache Control in Data SDK
- GraphQL Queries in Data SDK
- GraphQL API Developer Guide: Query Objects Examples