Комментарии 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 и другим решениям