Skip to content

Загрузка данных через service

Задача

Загружать удалённые данные через service и держать loading, data и error state внутри view model.

Решение

Передать service через dependency или другой внешний вход, хранить состояние запроса в atoms и выполнять асинхронный workflow внутри action view model.

Код

ts
import { declareViewModel, readonlyAtom } from '@nrgyjs/core';

type User = { id: string; name: string };
type UserService = { loadUser(id: string): Promise<User> };

export const UserScreenViewModel = (
  userService: UserService,
  userId: string,
) =>
  declareViewModel(({ scope }) => {
    const loading = scope.atom(false);
    const user = scope.atom<User | null>(null);
    const error = scope.atom<string | null>(null);

    return {
      state: {
        loading: readonlyAtom(loading),
        user: readonlyAtom(user),
        error: readonlyAtom(error),
      },
      load: async () => {
        loading.set(true);
        error.set(null);

        try {
          user.set(await userService.loadUser(userId));
        } catch (reason) {
          error.set(String(reason));
        } finally {
          loading.set(false);
        }
      },
    };
  });
tsx
import React, { useEffect } from 'react';
import { useAtoms, withViewModel } from '@nrgyjs/react';

const UserScreen = withViewModel(UserScreenViewModel)(({ viewModel }) => {
  const { loading, user, error } = useAtoms(viewModel.state);

  useEffect(() => {
    void viewModel.load();
  }, [viewModel]);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>{error}</div>;
  }

  return <div>{user?.name ?? 'No user'}</div>;
});

На что обратить внимание

  • состояние запроса должно жить рядом с view model, которая владеет screen flow
  • перед новым запросом обычно стоит очищать прошлый error state
  • во view лучше отдавать readonly state, а async work держать в actions

Частые ошибки

  • вызывать services напрямую из view
  • смешивать transport details с UI rendering code
  • не моделировать loading и error state явно