Перейти к содержанию
Mercury
Русский
Дизайн книга
Меню
Русский

Reflect.2. Вычисляем свойства

Подпись может зависеть от модели и префикса, который передал вызывающий компонент. mapProps получает эти значения при рендере и передаёт результат представлению.

Reflect 4.1.1 · Интерактивное упражнение

Открыть упражнение на всю страницу

Вычислите свойство из явных источников

Если значение относится к модели, используйте производное хранилище. Если оно нужно этому представлению и зависит ещё от входных свойств, подходит mapProps. Проекция получает значения источников и свойства после привязки и переопределений. Она должна возвращать значение, не вызывая события или эффекты.

import {createElement as h} from "@fiberfx/hyperscript";
import {store} from "@fiberfx/hypergraph";
import {reflect} from "@fiberfx/reflect";

const $name = store("Ada");
const $count = store(2);
const LabelView = (p: {prefix: string; text?: string}) =>
  h("p", null, p.text ?? "No label");
export const Label = reflect({
  view: LabelView,
  bind: {prefix: "Account"},
  mapProps: {
    text: {
      source: {name: $name, count: $count},
      fn: ({name, count}, props) => `${props.prefix}: ${name} (${count})`,
    },
  },
});
// h(Label, {})                         -> Account: Ada (2)
// h(Label, {prefix: "Member"})         -> Member: Ada (2)
// h(Label, {text: "Fixed"})            -> Fixed
// h(Label, {text: undefined})          -> No label

Источником может быть одно хранилище, плоский объект хранилищ, кортеж хранилищ либо {}, если нужны только входные свойства. Например, source: [$name, $count] as const передаёт в fn кортеж значений, а не два объекта Store.

Все проекции видят одни и те же базовые свойства. Одна проекция не получает результат другой. Связанные значения вычисляйте вместе в модели либо выводите независимо из их настоящих источников.

Измените модель и входные свойства

Откройте эксперимент с проекцией. Измените имя и префикс, затем задайте явную подпись. Пока переопределение включено, продолжайте менять источник. После этого попробуйте явно передать undefined.

Перед каждым действием предскажите подпись. Отсутствующий ключ и ключ со значением undefined имеют разный смысл: в первом случае действует значение по умолчанию, во втором оно заменено.

Проследите пропуск вычисления

Без переопределения изменение источника или префикса должно менять подпись. С фиксированным переопределением представление получает заданный текст. При явном undefined оно получает undefined и выводит собственное обозначение отсутствующего значения.

Перед вызовом проекции Reflect проверяет Object.hasOwn(props, key). Поэтому переопределённая fn не вызывается вообще, а не вычисляет скрытый результат. Учебный счётчик может показать вызовы, но рабочая проекция должна оставаться чистой. Пропуск вычисления не означает, что исчезли все подписки или повторные рендеры.

Уберите неоднозначность

Свойство text нельзя одновременно задать в bind и mapProps. Такой конфликт отклоняют и типы, и проверка во время выполнения. Вложенный источник {account: {name: $name}} тоже не поддерживается: каждое непосредственное значение объекта-источника должно быть хранилищем.

Функция, возвращённая проекцией, остаётся обычным значением. Она не становится действием, привязанным к области. Нельзя перенести обработчик из bind в mapProps и считать, что изоляция вызова сохранилась. В главе о замене компонентов это различие используется намеренно.

Верните вычисление по умолчанию

Уберите собственное переопределение и сбросьте эксперимент. Ещё раз измените префикс: подпись снова должна вычисляться. В коде приложения удалите ключ, а не передавайте {text: undefined}, если хотите вернуть значение по умолчанию.

Храните режим переопределения отдельно от исходных данных, чтобы проверять их независимо. Отсутствующее значение и намеренно пустое значение нередко выражают разные решения пользователя.

Сделайте строку состояния

Создайте представление с количеством из хранилища и названием сущности во входном свойстве: например, «Задач: 3» и «Сообщений: 3». Добавьте явное переопределение для уведомления о технических работах. Отдельно проверьте отсутствие ключа, заданный текст и явное undefined.

Для проверки объекта привязок используйте satisfies BindProps<Props>, если нужно сохранить сведения о явно заданных ключах. Необязательный ключ в широком типе привязки не гарантирует обязательное свойство представления. В следующей главе разместим вычисление в независимых областях состояния.

Назад · Курс · Далее