hydrate function

void hydrate(
  1. QueryClient client,
  2. DehydratedState dehydrated, {
  3. QueryDeserializeData deserializeData = _identity,
})

Merges a snapshot without overwriting newer client data.

Implementation

void hydrate(
  QueryClient client,
  DehydratedState dehydrated, {
  QueryDeserializeData deserializeData = _identity,
}) {
  for (final item in dehydrated.queries) {
    final serialized = item.state;
    final serverDataUpdatedAt = serialized['dataUpdatedAt'] == null
        ? null
        : DateTime.fromMillisecondsSinceEpoch(
            serialized['dataUpdatedAt']! as int,
          );
    final serverErrorUpdatedAt = serialized['errorUpdatedAt'] == null
        ? null
        : DateTime.fromMillisecondsSinceEpoch(
            serialized['errorUpdatedAt']! as int,
          );
    final now = client.scheduler.now();
    final updatedAt = _translateServerTime(
      serverDataUpdatedAt,
      dehydratedAt: item.dehydratedAt,
      now: now,
    );
    final errorUpdatedAt = _translateServerTime(
      serverErrorUpdatedAt,
      dehydratedAt: item.dehydratedAt,
      now: now,
    );
    final hasData = serialized['hasData']! as bool;
    final existing = client.queryCache.getAny(item.key.canonical);
    if (existing != null) {
      final current = existing.state;
      if (current.hasData && !hasData) continue;
      final currentDataUpdatedAt = current.dataUpdatedAt;
      if (currentDataUpdatedAt != null &&
          (updatedAt == null || !updatedAt.isAfter(currentDataUpdatedAt))) {
        continue;
      }
      final currentErrorUpdatedAt = current.errorUpdatedAt;
      if (!hasData &&
          currentErrorUpdatedAt != null &&
          (errorUpdatedAt == null ||
              !errorUpdatedAt.isAfter(currentErrorUpdatedAt))) {
        continue;
      }
    }
    final status = QueryStatus.values.byName(serialized['status']! as String);
    final state = QueryState<dynamic>.pending().copyWith(
      status: status,
      fetchStatus: QueryFetchStatus.idle,
      hasData: hasData,
      data: hasData ? deserializeData(serialized['data']) : null,
      dataUpdatedAt: updatedAt,
      error: serialized.containsKey('error')
          ? deserializeData(serialized['error'])
          : null,
      errorUpdatedAt: errorUpdatedAt,
      dataUpdateCount: serialized['dataUpdateCount']! as int,
      errorUpdateCount: serialized['errorUpdateCount']! as int,
      fetchFailureCount: serialized['fetchFailureCount']! as int,
      isInvalidated: serialized['isInvalidated']! as bool,
    );
    final query =
        existing ??
        client.restoreQuery<dynamic>(
          QueryKey<dynamic>(item.key.namespace, item.key.parts),
          state,
          meta: item.meta,
        );
    if (existing != null) setHydratedQueryState(query, state);
    final pending = item.pending;
    if (pending != null && existing?.isFetching != true) {
      unawaited(
        fetchHydratedQuery(
          query,
          pending.then(deserializeData),
        ).then<void>((_) {}, onError: (_) {}),
      );
    }
  }

  for (final item in dehydrated.mutations) {
    final options = client.getMutationDefaults(item.key);
    if (options == null) continue;
    final serialized = item.state;
    client.mutationCache.build<dynamic, dynamic, dynamic>(
      client,
      options,
      state: MutationState<dynamic, dynamic, dynamic>(
        status: MutationStatus.values.byName(serialized['status']! as String),
        data: null,
        error: null,
        errorStackTrace: null,
        failureCount: serialized['failureCount']! as int,
        failureReason: null,
        isPaused: serialized['isPaused']! as bool,
        variables: deserializeData(serialized['variables']),
        optimistic: deserializeData(serialized['optimistic']),
        submittedAt: serialized['submittedAt'] == null
            ? null
            : DateTime.fromMillisecondsSinceEpoch(
                serialized['submittedAt']! as int,
              ),
      ),
    );
  }
}