Назовите отображаемые состояния
Строковое хранилище выбирает явно заданную ветвь. Если ветви нет, используется default; без него ничего не выводится. Можно задавать неполную таблицу ветвей, но для неожиданных данных сервера полезен видимый запасной экран, который не выглядит как обычный пустой результат.
import {createElement as h} from "@fiberfx/hyperscript";
import {event, store} from "@fiberfx/hypergraph";
import {variant} from "@fiberfx/reflect";
const stateChanged = event<string>();
const $state = store("ready").on(stateChanged, (_, state) => state);
const Ready = () => h("p", null, "3 results available");
const Empty = () => h("p", null, "No results; change the filter");
const Failed = () => h("p", null, "Request failed; your draft is retained");
const Unknown = () => h("p", null, "Unknown state");
export const Result = variant({
source: $state,
cases: {ready: Ready, empty: Empty, error: Failed},
default: Unknown,
});
const $visible = store(true);
export const OptionalResult = variant({if: $visible, then: Result});
Логическая форма использует if, then и необязательный else. У OptionalResult нет else, поэтому при false он ничего не выводит. Обе формы поддерживают bind, mapProps и hooks по тем же правилам, что reflect. Выбираемые представления должны согласовать общий контракт свойств.
Сообщения в этих маленьких представлениях описывают состояния интерфейса. Сам variant не загружает данные, не сохраняет черновик и не повторяет запрос. Это обязанности модели. Используйте такой текст, только если соответствующее поведение действительно есть в приложении.
Выберите каждый результат
Откройте эксперимент с вариантами. Выберите готовый, пустой и ошибочный результат. Перед выбором Неизвестное: constructor предскажите, какое представление появится.
Сравните пустой экран и запасной вариант. Они должны сообщать о разных ситуациях: корректный запрос без результатов и значение, которое интерфейс не распознаёт.
Проследите явный выбор ветви
Готовый, пустой и ошибочный результаты должны открывать соответствующие ветви. Для constructor должен появиться явный запасной вариант. Reflect проверяет собственное свойство объекта, поэтому унаследованный член не становится ветвью.
Смена ветви может заменить выбранного потомка. Но хуки, переданные в variant, принадлежат общей связанной обёртке: они не запускаются при каждой смене ветви. Работу, относящуюся ко времени жизни конкретной ветви, размещайте в её компоненте. Глава о времени жизни объясняет, какие свойства сохраняют хуки.
Не выдавайте неизвестное за успех
Неизвестная ветвь не вызывает ошибку валидации: поддерживаемое поведение — запасной вариант либо отсутствие вывода. Показ запасного экрана не доказывает, что внешние данные прошли проверку. Если приложение требует отклонять неизвестные идентификаторы, проверяйте их в модели.
Не заменяйте защищённый выбор выражением cases[state] || Ready. Оно смешивает неизвестное состояние с готовностью, а обычный объект допускает унаследованные имена. Опубликованный variant проверяет принадлежность имени самой таблице ветвей.
Вернитесь в известное состояние
Перезапустите упражнение и убедитесь, что выбран готовый результат. Переключитесь с неизвестного состояния прямо на пустое: оно должно оставаться обычной явной ветвью. Для изменения хранилища состояния отдельный механизм восстановления не нужен.
В настоящем запросе сначала определите, что повтор меняет в модели, и только потом добавляйте кнопку. Переключение экрана само по себе не доказывает повторную отправку запроса.
Опишите результат поиска точно
Задайте модели поиска явные состояния: загрузка, готовый результат, пустой результат и ошибка. Сопоставьте каждому небольшое представление, общие свойства передайте через привязки и добавьте запасной экран для неизвестных внешних значений. Оставляйте предыдущие результаты на время загрузки только как осознанное решение продукта.
Логический variant подходит для простого условия присутствия. Строковый — когда состояния требуют разных объяснений. Далее заменим отдельный компонент внутри представления без выдуманного API слотов.