
Комментарии 20
А что насчет debouce?
Что насчет race condition?
А почему просто не использовать классику?
import { makeAutpObservable } from "mobx";
class SomeState {
fetching = false;
error = null;
item: IItem = null;
constuctor() {
makeAutpObservable(this);
}
fetchData = async () => {
this.fetching = true;
const ah = asyncHelpers(this.fetchData);
// Debounce + no race condition 300ms
if (!await ah.debouce(300)) return;
try {
const item = await new ApiReq(`GET /api/v1/item/${this.itemId}`)
.withCahe(60) // кэш 60сек
// для отмены запросов
.withAbort(ah.abortControllersArray)
.send()
// race condition check
if (!ah.stillActual()) return;
const itemComments = await new ApiReq(`GET /api/v1/item-comments/${item.commentsId}`)
.withCahe(60) // кэш 60сек
// для отмены запросов
.withAbort(ah.abortControllersArray)
.send()
// race condition check
if (!ah.stillActual()) return;
const data:IItem = {
...item,
comments: itemComments
}
this.item = data;
this.error = null;
} catch (e) {
// race condition check
if (!ah.stillActual()) return;
this.error = e;
} finally {
// race condition check
if (!ah.stillActual()) return;
this.fetching = false;
}
}
}Ну и дальше в компоненте
const MyList = observer(() => {
useState(() => { someState.fetchData(); });
if (someState.fetching) return <Spinner />
return (
<div className={styles.list_container}">
{someState.map(item => <div className={styles.list_item}>...</div>)}
</div>
)
});Под классикой вы видимо подразумеваете какой то ваш предыдущий проект, так как лично я многое здесь вижу впервые.
Что ж, по порядку:
Здесь использована магия (не все любят магию) mobx с ООП (многие считают эту парадигму неудачной), обертками компонент (увеличение vdom, стектрейса). Вынесем это за скобки ибо холивар разводить не хотелось бы.
Использована какая то неизвестная мне функция
asyncHelpersдляdebounceи отмены запросов.Использован неизвестный мне класс
ApiReq(опять ООП) в тч для кэширования запросов. Причем в данной реализации нет возможности принудительно запустить обновление данных, например через Pull to refresh - данные минуту всегда будут приходить из кэша. Неприятный баг UX.fetching каждый раз переходит в true, а в конце в false, тем самым показывая на короткое время спинер даже если данные уже закэшированы - UI баг. Возможно потребуется серьезный рефакторинг чтобы это исправить, если не полный отказ от данной архитектуры. Тут нужно смотреть на реализацию ApiReq.
Отсутствует нормализация - плюс множество проблем консистенстности данных в приложении, и увеличивается количеств запросов к серверу. Возможно придется полностью переписать архитектуру, чтобы ее прикрутить.
Данные item можно показать еще пока не погрузились комментарии, но не в данном примере. Потребуется рефакторинг.
Легко ли прикрутить, например, персистентность, SSR и тп?
Итого, мы имеем очередную собственную реализацию управления состоянием запросов, с проблемами, требующими серьезный рефакторинг, либо вообще полное переписывание приложения в случае, если потребуется все их исправлять (а значит на больших проектах - нерешаемых). Именно поэтому лучше не городить "свои решения", а использовать библиотеку, где большинство моментов уже продумали.
По поводу debounce в RRC:
Для query используется throttling - пока идет запрос с определенными параметрами, другие с теми же параметрами отменяются.
Для мутаций используется debounce - каждая следующая мутация отменяет предыдущую, если та еще не завершилась. Для этого вторым параметром в мутации передается abortController.signal.
Race condition там нет.
Здесь использована магия (не все любят магию) mobx с ООП (многие считают эту парадигму неудачной), обертками компонент (увеличение vdom, стектрейса). Вынесем это за скобки ибо холивар разводить не хотелось бы.
Object getter/setter магия?) Ну ок) Магия так магия)))
https://stackblitz.com/edit/vitejs-vite-fkgny3?file=src%2Fmain.ts&terminal=dev

Использована какая то неизвестная мне функция
asyncHelpersдляdebounceи отмены запросов.
Ну да, она легко имплементируется самостоятельно, ее АПИ же видно и понятно как она устроена и работает
Использован неизвестный мне класс
ApiReq(опять ООП) в тч для кэширования запросов.
Ну да, просто обертка для запросов к апи, она так же имплементируется самостоятельно, там тоже все достаточно просто и понятно исходя из примера использования.
Причем в данной реализации нет возможности принудительно запустить обновление данных, например через Pull to refresh - данные минуту всегда будут приходить из кэша. Неприятный баг UX.
Так то вообще легко, например можно в fetchData добавить аргумент force который в withCahe передаст null, что будет означать что кэш мы игнорируем и делаем запрос, опять же т.к. реализация своя можно всё что угодно добавлять.
fetching каждый раз переходит в true, а в конце в false, тем самым показывая на короткое время спинер даже если данные уже закэшированы - UI баг. Возможно потребуется серьезный рефакторинг чтобы это исправить, если не полный отказ от данной архитектуры. Тут нужно смотреть на реализацию ApiReq.
Т.к. MobX сконфигурирован на асинхронные реакции(включая автобатчинг), а они запускаются путём setTimeout, а внутри функции у нас промисты(микротаски), в момент испускания реакции значение fetching будет неизменным true и никаких спиннеров на короткое время не будет.
Вот как выглядит данная конфигурация

Вот как это в действии https://stackblitz.com/edit/vitejs-vite-vslbhn?file=src%2Fmain.ts&terminal=dev
Отсутствует нормализация - плюс множество проблем консистенстности данных в приложении, и увеличивается количеств запросов к серверу. Возможно придется полностью переписать архитектуру, чтобы ее прикрутить.
Вы о чем вообще? Пример просто из потолка написан, тут полная свобода, нужна нормализация - легко, не нужна - легко. Причем тут кол-во запросов к серверу? С чего вдруг что-то переписывать надо? Обрабатывайте данные как душе угодно.
Данные item можно показать еще пока не погрузились комментарии, но не в данном примере. Потребуется рефакторинг.
Легко, просто код чутка измените под эти нужды и всё, элементарно же.
Легко ли прикрутить, например, персистентность?
Да, мы же полностью контролируем код который мы пишем и делаем вспомогательные вещи под наши нужды без ограничений.
Именно поэтому лучше не городить "свои решения", а использовать библиотеку, где большинство моментов уже продумали.
Т.е. по вашему все вокруг идиоты, включая меня. И решения написанные нами это дно и их лучше не использовать. А вот если использовать библиотеку которую кто-то там написал(в том числе вы), вот уже совсем другое дело, там настоящий уровень и все так прекрасно и удобно. А если мне/Васе/Пете и т.п. не нравится то, что есть? Как быть? Ну не смешите такими выводами странными. Такие "выводы" канают только для начинающих.
Итого, мы имеем очередную собственную реализацию управления состоянием запросов, с проблемами, требующими серьезный рефакторинг, либо вообще полное переписывание приложения
Вы сами придумали "проблемы", которые кстати решаются по щелчку пальца, ибо описанное вами поведение нужно конкретно вам, а конкретно мне нужно другое поведение, а конкретно Васе нужно своё поведение и т.п.
Под классикой вы видимо подразумеваете какой то ваш предыдущий проект, так как лично я многое здесь вижу впервые.
Да любой проект, который писали опытные люди, в том числе классическое решение это функция/класс обертка для запросов к АПИ, в том числе события, на которые можно подписаться и перехватывать запросы/модицифировать их/универсальную обработку ошибок делать/ и т.д. и т.п. Так же классика это когда компоненты, которые используются в разных местах лежат в src/components и т.п.
Из того что вы ответили получается что вы практически реализовали свой фреймворк на базе mobx, который используете от проекта к проекту, но только не оформили его в библиотеку. Что то в этом фреймворке требует изучения далеко не очевидной конфигурации mobx (как пример где fetching всегда false), что то не реализовано совсем - нормализация, пагинация, персистентность и мн. др., тот же optimistic response, и разумеется чтобы их добавить "просто код чутка измените под эти нужды и всё, элементарно же". Вот только многое из этого не элементарно и потребует больших изменений, довольно багоемких, которые в идеале стоило бы еще и тестами покрыть.
Оформите вашу идею в библиотеку, добавьте туда многое из того что обсудили и то что есть у "конкурентов", и возможно любители mobx ее оценят.
Из того что вы ответили получается что вы практически реализовали свой фреймворк на базе mobx, который используете от проекта к проекту, но только не оформили его в библиотеку.
Ну по сути да, за 12 лет из которых 8 лет чистого фронта и множество разных проектов, грех не обзавестись кучей решений и подходов на все случаи жизни
Что то в этом фреймворке требует изучения далеко не очевидной конфигурации mobx (как пример где fetching всегда false)
Не надо ничего изучать, тебе сказали 1 раз, реакции асинхронные по умолчанию, отсюда и автобатчинг, и всё, ты это услышал и понял, 5 секунд изучения)
что то не реализовано совсем - нормализация, пагинация, персистентность и мн. др., тот же optimistic response, и разумеется чтобы их добавить "просто код чутка измените под эти нужды и всё, элементарно же"
Ну вообще да, без шуток. Любой каприз, берешь и делаешь.
Вот только многое из этого не элементарно и потребует больших изменений, довольно багоемких, которые в идеале стоило бы еще и тестами покрыть.
Ну для вас может и больших, багоемких и т.п. А для меня они маленькие, быстрые и достаточно простые, как и для любого опытного разработчика. который привык решать задачи самостоятельно, а не заклеивать дыры библиотеками.
Оформите вашу идею в библиотеку, добавьте туда многое из того что обсудили и то что есть у "конкурентов", и возможно любители mobx ее оценят.
И лишать разработчиков самой важной вещи - думать своей головой, чтобы для них все более и более элементарные вещи становились "проблемой" и под каждый чих они искали библиотеку. Ну нет, не такое будущее разработки я хочу видеть. Эти вещи слишком тривиальные чтобы пользоваться ими в рамках библиотек.
У меня другой опыт - я насмотрелся на опытных разработчиков, реализовывающих "каждый чих" самостоятельно, и все это многократно переписывал. В 95% случаев (если не чаще) все это работает плохо, забаговано, и на больших проектах не подлежит исправлению кроме как "выкинуть и написать с нуля". Про очень многие из лучших паттернов они даже и не в курсе (нормализация, optimistic response и мн. др.). Эти разработчики кстати чаще всего сами не видят никаких проблем в своем коде, и уж тем более не видят проблем в UX приложения.
У меня другой опыт - я насмотрелся на опытных разработчиков, реализовывающих "каждый чих" самостоятельно, и все это многократно переписывал.
Для начала с чего вы взяли что они реально опытные?) Например если человек Bob 15 лет работал на 2-3 проектах(а я таких знаю реально, прям лично), и человек Tom работал 5 лет на 10+ проектах, то Tom в 95% случаем будет на 3-4 головы лучшим разработчиком чем Bob который в опыте в годах аж на 10 лет больше работал. И это Tom построит гораздо более лучшую архитектуру на новом проекте, чем Bob, как минимум тупо за счет того что Tom видел в 3-4 раза больше проектов чем Bob.
Ну и конкретно в вашем сценарии вы видели плохих разработчиков, к великому сожалению их большинство( Так же как установщиков кондиционеров в лучшем случае 9 из 10 - плохие откровенно говоря, как тех кто ремонтирует автомобили, и т.д и т.п. Просто такова природа человека, в этом нет ничего удивительного и необычного, более того, таких людей никакие библиотеки не спасут, вот прям от слова совсем.
Откройте ваш проекты/любой проект допустим реактовский и посмотрите сколько в нем в зависимостях библиотек, а теперь внимание, по вашей логике код на этим проектах должен быть в худшем случае идеальный. а если там библиотек больше 20-30, так вообще великолепный, без вариантов, ведь люди столько идеальных готовых решений примели и у них просто нет шансов на ошибки и на плохой код.
А теперь окунемся в реальность. в лучшем случае код на этих проектах будет очень средненьким с натяжкой, а в среднем плохим, иногда ужасным.
Какая мораль? Никакие библиотеки/фреймворки и т.п. ни от чего не спасают(разве что чуть чуть), если руки из нужного места растут, то все будет отлично, как без библиотек, так и с библиотеками, а если нет, то соответственно все будет плохо.
В 95% случаев (если не чаще) все это работает плохо, забаговано, и на больших проектах не подлежит исправлению кроме как "выкинуть и написать с нуля".
Возможно вы сами себе придумали критерии и по ним оценили что всё работает плохо. А если посмотреть объективно со стороны, то по факту все работает как минимум нормально. а то и хорошо.
Эти разработчики кстати чаще всего сами не видят никаких проблем в своем коде, и уж тем более не видят проблем в UX приложения.
Зависит от ваших индивидуальных критериев к коду. Мало ли, может вы пишете вложенные друг в друга теранарки, или не делаете early return в функциях(в том числе реакт компонентах), или вместо async/await пишете цепочки .then и т.д. и т.п. И считаете что это нормально и правильно, а другой код плохой.
Хотя если быть честными самими с собой, то код, который ты читаешь первый раз сверху вниз и понимаешь что он делает, что будет дальше, какой будет результат его выполнения - это хороший код.
А если ты смотришь и не понимаешь, без документации, без задавания вопросов автору кода и т.п. - этот код плохой.
Но бывают и исключения из этих правил. в случаях когда очень сложная и навороченная бизнес логика, в таких случаях код будет плохим неизбежно и без вариантов. Где-то чуть менее плохим, где-то чуть более плохим, но суммарно плохим.
redux....
На хабре принято писать конструктивно - это же не религиозный культ очередного убийцы redux.
Он имеет в виду, что использовать redux(и всё что вокруг и около него) вместо mobx в наше время, это нелепо. Да и в 2019 году уже было нелепо)
Я думаю что судя по его комментам он бы сказал то же и про mobx в угоду effector, а я бы сказал так про mobx и effector в угоду redux) А в соседней статье любители хайпа отказываются от effector после года мучений и в очередной раз выбирают технологию без должного анализа)
Вот только профессионалы как использовали redux и не имели с ним никаких проблем, так и используют. Потому что это самый простой, а значит лучший инструмент.
Да ну? Не, ну чистый redux наверное, но по сравнению с redux-toolkit все уже не так превосходно в mobx.
По сравнению с redux-toolkit, MobX тоже на 100 голов лучше.
MobX это библиотека для тех, кто в архитектуре не разбирается. Ее вообще не стоит где либо использовать, пора уже похоронить.
MobX это библиотека для тех, кто в архитектуре не разбирается.
Ахахах. Ну ка, давайте ка прям конкретно по пунктам, с чего это вдруг?)
Ее вообще не стоит где либо использовать, пора уже похоронить.
1) Ахахах, сказал тот, кто юзает redux. Это уже говорят о вас многое, увы не лучшую сторону. И это не пустые слова, вы их подтверждаете постоянно, когда что-то пишите.
2) Сказал тот, чьи слова - пустой звук:
Вот например:
17 сентября 2024г.
https://habr.com/ru/companies/vk/articles/839632/comments/#comment_27305502
В том числе рассмотрел бы возможность сделать тоже самое на основе обычного useRef без лишних библиотек.
Вам скинули пример, а вы так и не сделали тоже самое, только на основе обычного useRef без лишних библиотек. Просто игнор, как будет ничего не было) Сегодня 2 декабря карл. 2.5месяца+ прошло. Так что то, что вы пишете просто бла бла бла.
15 сентября 2024г.
https://habr.com/ru/companies/vk/articles/839632/comments/#comment_27295060
Вы обсирали ООП, когда запросили конкретику, то вы:
Многих людей) Но холивар предлагаю здесь не устраивать. Просто есть такое мнение. Я статью пишу по этому поводу, вас обязательно позову.
Сегодня 2 декабря карл. 2.5месяца+ прошло. Опять бла бла бла.
И это так, чисто цветочки. Дальше мне просто лень вас тыкать носом в лоток. Иначе этот комментарий будет размером как 2 статьи. А такого рода ваших комментов, где вы просто в один момент начинаете игнорировать, когда в вашу чушь, вас очередной раз тыкают носом полно. Что очередной раз подтверждает, что все на что вы способны это писать бла бла бла "аргументы", ценность которых - абсолютный ноль.
С чего бы мне приводить какие либо аргументы человеку, который до этого уже написал 2 комментария без каких либо аргументов.
В той статье очень много спорщиков, терять время каждому что то доказывая я не собираюсь, я и так потратил на это слишком много времени, и считаю что этого достаточно. Может как нибудь напишу статью про лучший стейт менеджер, а не буду спорить до бесконечного в комментариях.
Я действительно пишу статью и она выйдет после НГ. В приоритете до этого была другая статья про стили в RN, вышла недавно, можете ознакомиться.
И какой смысл требовать от кого то если вы сами пишете что не готовы спорить - "лень".
Опять пустой выброс отмазок и отговорок, лишь бы съехать с темы и не отвечать на конкретные моменты в которые ткнули носом.
https://habr.com/ru/companies/vk/articles/839632/comments/#comment_27305502
В том числе рассмотрел бы возможность сделать тоже самое на основе обычного useRef без лишних библиотек.
Вам скинули пример, а вы так и не сделали тоже самое, только на основе обычного useRef без лишних библиотек. Где???
Ответил. Предлагаю данное обсуждение вернуть туда. Хотя я совсем ненадолго, что то доказывать кому то лень, как и вам. Тем более если диалог не конструктивен, а у собеседника проблемы с мышлением и вырываем слов из контекста.
Ответил
Ну вообще нет, не ответили. Опять попытались отмазаться от ответа и не более того.
Тем более если диалог не конструктивен, а у собеседника проблемы с мышлением и вырываем слов из контекста.
Ищите любые "предлоги" для своих отмазок и пытаетесь их оправдать. Но только это сразу видно и очевидны, что вы просто соскакиваете с конкретных ответов, ибо знаете что не правы, но боитесь это признать.
Хотя я совсем ненадолго, что то доказывать кому то лень, как и вам.
Да-да, классическая защитная реакция, якобы вам лень, якобы вы выше этого и т.д. и т.п. Это все классические отмазки тех, кто заведомо знает что не прав, а заднюю давать мужества не хватит. Там же все предельно понятно, вам дали код, с вас требуется ответный код. Всё предельно ясно и понятно.
Библиотека RRC для управления запросами и кэшем на базе Redux: [лучшая] альтернатива RTK-Query и другим решениям