↵ Вернуться

Структура моделей Effector

Table of contents

Введение

Во время работы, у меня есть три состояния:

Во время чтения и изменения кода, мне необходимо четко понимать какую задачу решает каждый кусок кода в файле, в какой сценарий складываются эти кусочки и как работают вместе файлы логики в проекте.

Написание нового кода, я начинаю с проектирования внешнего интерфейса файла, с событий которые необходимых в этом блоке логики.

Какие-то файлы описывают user story, другие — сущности. Детали подхода для каждого из типов файлов несколько отличаются, но код однозначно должен читаться сверху вниз: определения, логика, детали реализации.

Model

Вне зависимости от типа, я называю модуль с логикой на эффекторе — модель.

User Story

Чаще всего один или несколько схожих сценариев, решающих одну задачу пользователя. Такой тип модели использую в страницах и организмах фичи, подробности в предыдущей статье Структура приложения.

Entity

Данные описывающие одну сущность и события ее модифицирующие. У таких моделей обычно нет сценария использования и они лежат в models/ директории фичи.

Структура

Модуль поделен на логические блоки идущие в строгом порядке, блоки разделены между собой пустой строкой.

Порядок блоков в модели:

  1. Типы
  2. События
  3. Эффекты
  4. Сторы и вычисляемые сторы
  5. Логика в виде связей
  6. Детали реализации

Типы

type InputEvent = SyntheticEvent<HTMLInputElement>;
type Form = {
  login: string;
  password: string;
  remember: boolean;
};

const MINIMUM_TIMEOUT = 100;

События

export const pageMounted = createEvent<void>();
export const loginChanged = createEvent<InputEvent>();
export const buttonPressed = createEvent<ButtonEvent>();
const buttonTypePressed = submitPressed.map(
  (event) => event.currentTarget.type,
);

const loginSaveFailed = createEvent<string>();

Эффекты

export const saveLogin = createEffect();
const saveLoginFetching = createFetching(saveLogin, 'loading');

export const loadLogin = createEffect();

Сторы и вычисляемые сторы

const $login = createStore('');
const $password = createStore('');

export const $isLoginValid = $login.map(loginValidator);
export const $isPasswordValid = $login.map(passwordValidator);
export const $isFormValid = eachTrue([
  $isLoginValid,
  $isPasswordValid,
]);
export const $form = combine({
  login: $login,
  password: $password,
});

Логика в виде связей

$login.on(loginChanged.map(trimEvent), (_, login) => login);
$login.reset(pageMounted);

sample($form, submitPressed).watch(loginUser);

loginUser.use(authApi.login);

Детали реализации

function trimEvent(event) {
  return event.currentTarget.value;
}
↵ Вернуться