setQueryData<TQueryData> method

TQueryData setQueryData<TQueryData>(
  1. QueryKey queryKey,
  2. TQueryData data, {
  3. DateTime? updatedAt,
})

Writes data into the cache, creating the entry if needed.

Every observer of the key sees the new data at once, and the entry counts as freshly fetched (updatedAt, default now) — the tool for optimistic updates and for putting a mutation's response into the cache without a refetch:

client.setQueryData<Todo>(QueryKey(['todos', todo.id]), todo);

The type argument is inferred from data, and a value infers narrowly: setQueryData(key, 'x') is a String write. An entry that already exists takes any value its own type can hold, so that write lands in a query holding String?, and a sealed type's variant lands in a query of the sealed type. A value the entry cannot hold throws QueryDataTypeError. The type argument still decides the type of an entry this call creates — name it when seeding a key before its query exists: setQueryData<List<Todo>>(key, []).

Returns what the cache now holds: after structural sharing, that is the instance already cached when data is deep-equal to it.

A bare setQueryData(key, null) — the type argument inferred as Null — writes nothing and returns null, as TanStack Query's setQueryData(key, undefined) does. To store null, name the entry's nullable type: setQueryData<Todo?>(key, null).

Implementation

TQueryData setQueryData<TQueryData>(
  QueryKey queryKey,
  TQueryData data, {
  DateTime? updatedAt,
}) {
  // A bare `setQueryData(key, null)` infers `Null`: upstream's
  // `setQueryData(key, undefined)`, which writes nothing. Written, it
  // nulled the data of an existing entry, or created a `Query<Null>` that
  // made every typed reader of the key throw until it was collected. A
  // deliberate null write names the entry's type:
  // `setQueryData<Todo?>(key, null)`.
  if (TQueryData == Null) {
    return data;
  }
  final existing = queryCache.peek(queryKey);
  if (existing != null &&
      existing.dataType != TQueryData &&
      _holds<TQueryData>(existing, data)) {
    // What sharing stored, as the typed path and upstream return it; the
    // argument only when the stored value is not a `TQueryData` — an older
    // instance of a wider type kept by sharing.
    final stored = existing.setData(data, updatedAt: updatedAt, manual: true);
    return stored is TQueryData ? stored : data;
  }
  final query = queryCache.build<TQueryData>(
    this,
    defaultQueryOptions<TQueryData>(
      QueryOptions<TQueryData>(queryKey: queryKey),
    ),
  );
  return query.setData(data, updatedAt: updatedAt, manual: true);
}