Signal-components – Telegram
Signal-components
62 subscribers
15 photos
13 links
Новости signal-components
Download Telegram
Раз у нас образовался эдакий андеграунд, давайте я опишу про что проект и какие у него цели:

Основная причина его появления: https://news.1rj.ru/str/xavescor_code/142. Реакт считает верной концепцию(логика через ререндер), которая для меня тупиковая. Поэтому цель у проекта простая:
- Дать возможность пользователю писать приложение на реакте, используя 0 хуков
- Сократить количество и размеры ререндеров до минимально возможных. Компонент не должен ререндериться, если в нём ничего не изменилось
- Сохранить 100% совместимость с реактом, чтобы можно было использовать его экосистему
- Оставить пользователю возможность использовать хуки, чтобы переход был максимально гранулярным.
- Дать возможность пользователю внедрять реактивность в любом месте приложения, чтобы максимально упростить переход.

Как я этого планирую достичь:
Я считаю, что мы можем сделать биндинги к реакту для любого реактивной системы описания логики с derived сторами(далее стм). К таким стм сейчас относятся reatom, effector, proposal-signals. Эти системы обладают главным качеством, который позволяет предотвратить лишний ререндер: они не продолжают вычисление, если в сигнале/сторе/атоме(далее атомы) оказалось такое же значение.

На данный момент для написания прототипа был выбран reatom, так как у него есть очень хороший шорткат для моей текущей задачи: это https://www.reatom.dev/package/npm-react/#reatomcomponent. У эффектора и proposal-signals, к сожалению, подобного нет. Поэтому я сначала хочу сделать публичное апи, а потом дать доступ к работе со стороны других стм.

Основная идея:
- У нас есть 2 фазы работы компонента
- фаза инициализации, в которой мы можем инстанцировать функции, атомы и всё что мы хотим. Это позволит нам иметь одну и ту же копию во время всей работы компонента
- фаза ререндера. В этой фазе пользователь может писать привычный реакт код.
- Пропы прилетают только во время фазы инициализации в виде Record<string, Atom>. Это позволит нам иметь стабильные ссылки на все пропы в компоненте, не ретригеря ререндер, если внаружи пришло тоже самое значение. Во время фазы ререндера доступа к пропам нет. Используйте то что у вас есть в фазе инициализации
- Снаружи можно передавать Atom<T> | T. signal-components сами превратят значение в атом, если это требуется. Это позволит снять пользователю головную боль, связанную с прокидыванием значений из среды ререндера в реактивную среду
- Мы можем оборачивать любой компонент в declareComponent и это не будет влиять на остальную логику приложения. Это позволит пользователю легко за сверхкороткое время(минут 5) оценить бенефиты реактивности.


Ну, вот как-то так. Если есть вопросы, то готов ответить, так как возможно у меня взгляд замылен и я не совсем всё проработал.

Ещё одна демка на посмотреть: https://codesandbox.io/p/sandbox/signal-components-simple-example-74tdrh. Прекрасный пример как стм помогает нам избежать лишних ререндеров.

Так же советую глянуть тесты, которые примерно показывают кейсы, которые уже поддерживаются библиотекой: https://github.com/XaveScor/signal-components
👍3
В v0.5.0 появляется метод ctx.component:

Это возможность рендерить содержимое сигнала сразу в компонент(далее Х), что позволяет нам не ререндерить текущий компонент(далее P) при изменении сигнала и не ререндерить X при необходимости ререндеринга P.

Подробнее:
Демо: https://codesandbox.io/p/sandbox/signal-components-ctx-component-cktdkh
Тесты: https://github.com/XaveScor/signal-components/blob/f3c57aad5ab84b59650c1cb8d097e919f2c9b70a/src/index.test.tsx#L232-L249
👍4
v0.6.0

Исправления:
- [Регрессия]Были возвращены все методы в ctx, которые были удалены в v0.5.0
- Имена стабильных функций стали строже. В имени пропа после префикса on должна быть заглавная буква([A-Z]). Демо
- Добавлено ограничение на уровне типов: стабильные функции обязаны возвращать тип void.
- Исправлена логика по пробросу нестабильных функций. До этого эта фича попросту не работала. Демо

Новые фичи:
- ctx.component теперь может принимать на вход функцию(`ctx.component(anAtom, mapper)`), которая позволяет замапить содержимое атома перед рендером. Демо
Преимущества никак не изменились. Изменение атома или маппера в ctx.component никак не вызывает ререндер родителя.
Новая особенность: если маппер возвращает тоже самое значение, то ререндера ctx.component не происходит. Это требуется, для того, чтобы между ререндерами компонента-родителя не было необходимости мемоизировать маппер. Т.е. вы спокойно можете писать ctx.component(anAtom, x => x + 1) и не думать о том, что mapper будет пересоздан при ререндере родителя.
👍1
v0.7.0

Новинки:
wireHook - функция, которая позволяет "запаковывать код на хуках в атом". Теперь вы можете в стабильной области писать обычный код на хуках. Это позволит вам ещё более гранулярно перейти на нормальные реактивные рельсы. Так же, возврат из функции оборачивается в атом, что позволяет его использовать далее при вычислениях.
Demo: https://codesandbox.io/p/sandbox/signal-components-wire-hook-cx48z7
Тесты: https://github.com/XaveScor/signal-components/blob/dcde71210ec7d3cceffa060da37dc88c11861b6f/src/hooks.test.tsx


[BREAKING]:
Теперь рендер функция не возвращает ctx первым аргументом. На его месте {spy, component, reatomContext}. Эта схема позволит в будущем отвязать логику signal-components от текущей версии реатома, что позволит портировать SC на другие реактивные системы типа effector или proposal-signals.
1🔥1
Отчёт о попытке интеграции signal-components@0.7.0(далее SC) в наш боевой проект:

1) Полетели third-party библиотеки react-i18next и react-router@6. SC попросту не смог переварить ререндер у этих библиотек.
Буду заниматься отдельными пакетами интеграции для них, чтобы отдебажить проблему и иметь удобные биндинги

2) Иметь локальный wireHook сверхнеудобно для описывания интеграций. Буду делать его глобальным по типу React.use*

3) Нужно срочно отдельное апи для провайдера, так как

wireHook(() => useContext())

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

v0.8.0 будет направлена на решение этой задачи.

4) Нужно будет вытащить внаружу логику, которая из T | Atom<T> делает Atom<T> прозрачно для пользователя. Это требуется для кастомных апишек пользователя, где хочется иметь возможность передавать как атом, так и скаляр.

5) В оппозицию к пункту 3, я не буду делать функции spy глобальными, так как моя цель делать ререндеры максимально точечно. И spy, как и wireHook - это костыли, для связи между реактивным миром и реактовским. И в идеальном коде они должны отсутствовать.

6) Нейминг для функций, которые вызываются связывают реакт-мир и реактивный мир, в виде wire* - вполне удобный и различимый.

Если есть мысли, то велком ту обсудить. Не стесняйтесь) Фидбек всегда полезен.
🔥3👍1
v0.8.0

- [Breaking] wireHook - теперь глобальная функция. Это позволяет упростить написание биндингов от реакта к signal-components.
Однако, с этим добавляется ограничение. В проекте обязана быть установлена только ОДНА версия signal-components. Если будет несколько, то wireHook будет работать некорректно.
Демо: https://codesandbox.io/p/sandbox/signal-components-wire-hook-cx48z7
v0.9.1

getAllPropsSignal - новая функция, которая позволяет получить сигнал, который содержит все пропсы, переданные компоненту.

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

Demo: https://codesandbox.io/p/sandbox/signal-components-all-props-signal-yh843s
v0.10.0 part1

Добавлена функция wrap, которая позволяет взаимодействовать с third-party компонентами как с компонентами на signal-components.

Плюсы:
- вы можете передавать в обёрнутый компонент сигналы и будет обновляться как будто в в него передаёте нереактивные значения.
- При изменении пропов будет ререндериться только обёрнутый компонент и ничего более.

Demo: https://codesandbox.io/p/sandbox/signal-components-wrap-wytpm5
🔥1
v0.10.0 part2
Добавлена фабрика html.

html - это набор базовых html компонентов, которые обёрнуты в функцию wrap из https://news.1rj.ru/str/signal_components/12. Это позволяет упростить код, передавая в базовые теги сразу сигналы, пропуская фазу подписки.

Demo: https://codesandbox.io/p/sandbox/signal-components-html-s9r75m
👍2
v0.11.0

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

Так же добавлена специфичная функция для реатома bindCtx, которая позволяет забиндить реакт контекст к экшену.

Demo: https://codesandbox.io/p/sandbox/signal-components-return-jsx-kcfgjp

Так же, если есть возможность, то тыкните звёздочку https://github.com/XaveScor/signal-components
Вчера я закинул один из постов в реакт чат и столкнулся с полнейшим непониманием того что из себя представляет signal-component. Поэтому хочется чуток описать свои мысли:

Мысль первая: в случае реакта АБСОЛЮТНО ВСЯ логика должна быть в стейт менеджере. В идеальном приложении должно быть 0 хуков
Мысль вторая: у нас есть 2 хороших стейт менеджера @reatom_ru и @effector_ru, которые форсируют пользователя писать логику глобально.
Мысль третья: условие из мысли 2 мешает внедрять стм в текущее приложение
Мысль четвертая: все кто предоставляет "исправления реакта", такие как преакт, солид и прочие попросту ломают обратную совместимость с реактом и не дают людям писать логику в лучшем стиле.

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

Основные идеи SC донельзя проста:
1) мы вводим 2 фазы выполнения компонента: init и render. init выполняется во время первого рендера и кешируется для последующих ререндеров. render работает как и в реакте
2) мы можем получать внутри компонента пропы исключительно в виде атомов/сторов(далее сигналы). Это позволяет нам сразу писать реактивную логику поверх пропов
3) SC представляет концепцию реактивных компонентов, в пропы которых можно передавать как сигналы, так и примитивные значения. SC сам обернёт значение пропа в сигнал
4) В идеале render слой пропадает и мы попросту возвращаем "реактивный jsx". См. https://news.1rj.ru/str/signal_components/15
5) SC позволяет переписывать только то что вам нужно в данный момент: если вам нужно использовать хуки, то используйте хуки. Это не проблема. Хуки сможете переписать в другое время. См https://news.1rj.ru/str/signal_components/9
6) SC не навязывает то как вам надо писать код. Если вы в итоге захотите вытащить код в глобальную область видимости - вы с лёгкостью сможете это сделать. Если же вы пока не уверены в этом - оставляйте логику внутри компонента.

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

Ну и исходники: https://github.com/XaveScor/signal-components. Я очень серьёзно отношусь к тестам. По идее, из них тоже будет ясна идея продукта.
Ну и пример как постепенно переписывается компонент. Всё максимально гранулярно.

Важно заметить: снаружи вызов компонента никак не меняется. И любая из версий компонента из скриншота является полностью рабочим кодом.

Demo: https://codesandbox.io/p/sandbox/signal-components-artalar-demo-43rphv
🔥1
v0.12.0
Полностью переписаны тайпинги.

К сожалению, типы даже на этом моменте уже стало тяжело поддерживать. В предыдущих релизах была некорректная работа с опциональными on* функциями.

Переписывание типов и их покрытие тестами позволило поправить этот и некоторые другие неочевидные баги. Подробнее об этом написано тут https://news.1rj.ru/str/xavescor_code/160

Демо: https://codesandbox.io/p/sandbox/signal-components-html-s9r75m

P.S. чтобы увидеть разницу, нужно откатиться на v0.11.0. Тогда вы увидите ошибки тайпскрипта.
👍3