Pull to refresh

Comments 22

Из текста не очень понял несколько вещей.

Вот для чего нужна вот эта вундервафля?

export function createQueryKey<T extends unknown[]>(namespace: string, ...args: T) {
  return [namespace, ...args] as const;
}

На вид, все что она делает заменяет это:

export const userQueryKeys = {
  ...

  card: (id: string) => ['users', id, 'card'] as const,
  ...
};

На это:

export const userQueryKeys = {
  ...
  card: (id: string) => createQueryKey('users', id, 'card'),
  ...
};

Это ее единственная функция?

Плюс, не очень понял как пользоваться userQueryKeys

Например, у нас есть userQueryKeys.card который состоит из 'users', id, 'card' на вид это выглядит так, что совершенно валидно инвалидировать все карточки использовав предикат:

queryClient.invalidateQueries({
  predicate: (query) =>
    query.queryKey.includes(userQueryKeys.cardAll) // cardAll: 'card'
})

Но тогда возникает вопрос, а не удобнее было бы семантически группировать ключи? Что бы все, что относится к card было в одном месте.

И тут возникает третий вопрос, а почему решили не рассматривать подход, который предлагают рассмотреть в доке к https://tanstack.com/query/latest/docs/framework/react/guides/query-keys#further-reading, а именно https://github.com/lukemorales/query-key-factory

Да, это просто по факту меняет вид написания, на вид стало лучше, как мне кажется

export function createQueryKey<T extends unknown[]>(namespace: string, ...args: T) {
  return [namespace, ...args] as const;
}

userQueryKeys, в данном случае централизует, ключи по категории например user

Если рассматривать именно на этом коде

export const userQueryKeys = {
  all: () => createQueryKey('users'),
  byId: (id: string) => createQueryKey('users', id),
  card: (id: string) => createQueryKey('users', id, 'card'),
  byFilters: (filters: UserFilters) =>
    createQueryKey('users', 'filters', JSON.stringify(filters)),
};

то вызывая

queryClient.invalidateQueries({ queryKey: userQueryKeys.card(543) });

мы инвалидруем только карточку юзера с id 543, а если будет

queryClient.invalidateQueries({ queryKey: userQueryKeys.all() });

то всю бизнес сущность юзера, как каждого, так и каждого по id, так и карточку каждого пользователя, а ещё по фильтру

запись коротка и радует глаз, опять же как мне кажется
А вот такой либы https://github.com/lukemorales/query-key-factory, у нас нет в нексусе, из-за особенностей сферы разработки, а базовый подход слишком сильно развязывает руки разработчику и децентрализует ключи, опять же как мне кажется.

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

используя связку FSDTanStack RouterTanStack Query и Effector

Вы конечно собрали комбо из самых худших подходов. Зачем?

Классическая архитектура, React, MobX, SCSS + CSS modules - идеальный выбор ещё с 2016 года и по сей день.
Для роутинга либо самописное решение. Из готовых, всё гуано.
Для АПИ запросов самописная обертка, которая использует axios. Из готовых, всё гуано.
Для работы с формами и валидацией, то же самописное решение. Из готовых, всё гуано.

Более того, React нужно использовать исключительно как View слой, а не как средство для управления состоянием и т.п.

P.S. React way === Худший путь.

Очень субъективно и с устаревшим взглядом, так можно и на ванильном JS писать без библиотек, все на самочинном, не желание принять развитие окружения чревато.

Выбирать mobx когда команда его не знает равносильно выстрелу в ногу, использовать модули на scss в 2025м году, когда css убил препроцессор в после ~21го года - сомнительное решение

Зачем тратить время на возможно кривые самописные решения в заказной разработке где сжатые сроки на релизы?

С такими суждениями бы окунуться в актуальные решения, имхо, собственно как и ваше

Ну Mobx не то чтобы сложен. Пишем в обычном стиле где сторы и ViewModel - это классы, добавляем makeAutoObservable - получаем автоматический точечный ререндер компонентов при изменении только тех свойств, которые используются в компоненте.

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

А вот чем CSS Modules и scss не угодили?

Модули позволяют исключить пересечение стилей между компонентами, дают быстрый переход на место объявления, позволяют настраивать именование класса (например включать путь src-components-layouts-layoutWrapper), что создает ясный идентификатор для компонентов. Для e2e тестов не подойдет, но для дебага - прекрасно, сразу видно кнопку в каком из 100 компонентов, использующих кнопки, нажал пользователь и получил ошибку. Также при желании можно настроить генерацию d.ts файлов из стилей, чтобы найти все неиспользуемые классы (на постоянной основе - нежелательно, но в качестве плановой оптимизации раз в 3 месяца - отлично).

Scss - это миксины, nesting (вложение одних классов в другие), математика и циклы, удобные импорты. Не обязательно использовать именно препроцессоры - можно использовать сразу постпроцессоры (PostCSS) с соответствующим интерпретатором. Во многих проектах постпроцессор и так используется (для автопрефикса и оптимизации например), и добавление scss не сильно ухудшит перфоманс сборки, но добавит удобный DX.

Ну, про FSDTanStack RouterTanStack Query и Effector я согласен с предыдущим комментатором, что сейчас это самое неэффективное, и это никак не связано с годом их выпуска. Но популярных альтернатив лучше и правда мало, и если сжатые сроки - то можно и затянуть в проект, особенно если команда хорошо с ними знакома.

Не, я не против mobx, тут да, от команды зависит

Я использую как раз модули, тут тейк был про scss именно, что он по факту не нужен, сейчас с актуальными возможностями css базового (включая модули) без препроцессоров можно обойтись в 99% случаев

Миксины фича, но не всегда нужна, можно и без них, тем более ради одних миксинов замедлять сборку, все равно в css обычный по итогу перейдет

С вложенностью сложно, у нас в командах почему то не любят вложенность классов scss, если даже используют, то пишут всё в строку.

По факту надобности сильной в scss нет, ипорты есть и базовом css.

На момент написания стати этот стек довольно неплох, с одним НО, в effector в этом решении используется не для флоу данных в проекта, а как средство проброса ивентов и эффектов

В вашем контексте "разработка навынос", то есть заказная, сроки - сжатые, команда - минимальная и низкой квалификации, статья и аргументы годные для "песочницы". Но Хабру это пользы не несет, поэтому поставил минус за низкое качество материала. После 20 таких проектов - сами увидите, насколько плох был подход и подобранные библиотеки.

А давно хабр стал местом куда могут постить только «полезные» как вам кажется статьи? (Никогда таким и не был, как бы вам этого не хотелось)

Ладно, ваше мнение)

Троллинг? Напишите валидный нестинг на css, опишите поддерживаемые браузеры. Никому не нужен такой бесполезный коммент

"возьми почитал" мобильный Сафари 17.2. Интересно, на какие страны вы делаете приложения - в Америке валом старых айфонов, в России - тем более, в Азии 17 еще не видели.

В контексте "еще в 2021 css убил scss" ну сами посмотрите

"возьми почитал" мобильный Сафари 17.2. Интересно, на какие страны вы делаете приложения - в Америке валом старых айфонов, в России - тем более, в Азии 17 еще не видели.

вряд ли сейчас, кто-либо, для больших продакшенов пишет на нативном css без использования транспиляторов

lightningcss

React как view устарел) Его подход с ререндером компонентов даже с Mobx вызывает всю цепочку сравнений VDOM. В целом он очень неоптимизирован. React is ecosystem пока остается актуальным.

Классическую? кто эти плохие практики с мобх, сасс записал в классику? Не нужно свои фантазии выдавать как за идеальный выбор.

Классическую?

Да, классическую.

кто эти плохие практики с мобх, сасс записал в классику?

  1. Они не плохие, они лучшие для фронта.

  2. Их туда записано сообщество настоящих разработчиков и адекватных людей.

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

Не нужно свои фантазии выдавать как за идеальный выбор.

Это не фантазии, это объективная реальность. На данных момент безальтернативная. Альтернативы хуже с точки зрения удобства разработки, качества кода и красоты этого самого кода. А это золотая середина.

Вызывает смех да и только. Не буду мешать жить в розовом мире

Вызывает смех да и только. Не буду мешать жить в розовом мире

Да да, оправдывайте свою некомпетентность в качестве разработчика и говнокод тем, что я якобы не ведаю о чем говорю и живу в розовом мире)

Я как раз живу в реальном мире и прикладываю все усилия чтобы моя жизнь была максимально легка и без сложностей.
Поэтому и использую react+mobx+css modules+классическую архитектуру чтобы максимально легко и непринуждённо разрабатывать любые проекты, вместо того чтобы страдать, решать надуманные проблемы и т.п..

не найдя хороших материалов по теме организации queryKeyв TanStack Query

Есть статья от создателя Tanstack Query про эффективное описание ключей.
Из нее (и на практике) я подчеркнул, например, что порой нужно инвалидировать списки отдельно от деталей, если данные деталей подставлены в кеш напрямую из ответа мутации.

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

type QueryKeys<T extends string> = {
    all: [T];
    lists: [T, 'lists'];
    list: (params: Record<string, unknown>) => [T, 'lists', typeof params];
    details: [T, 'details'];
    detail: (id: string | number) => [T, 'details', typeof id];
};

function generateKeys<T extends string>(base: T): QueryKeys<T> {
    return {
        all: [base],
        lists: [base, 'lists'],
        list: (params) => [base, 'lists', params],
        details: [base, 'details'],
        detail: (id) => [base, 'details', id],
    };
}

const userQueryKeys = generateKeys('user')

Возможно, это будет Вам полезно.

Спасибо, обязательно посмотрю, очень полезно

Из личного опыта у FSD ужасный длинный нейминг, что не позволяет создавать странички копи пастой, меняя пару хендлеров вызвов апи Tanstak query лучше использовать в виде функции которые нужно вызывать в контролируемом режиме, без всяких enabled. Инвалидация старых данных там боль. Можно написать над этим обертку, но зачем тогда Tanstak. Лучше написать свою. В целом тоже сомнительная вещь.

Ну в моей реализации все пришло к тому что хуки запросов оборачиваются в хук/функцию, и вызываются где надо с прокидыванием внутрь параметров нужных, а энейблед чисто что бы запросы не вызывались с undefined если их кто то просто так хочет вызвать

Fsd по факту загоняет хаос немного в рамки, да есть минусы, они есть везде, просто надо принять с какими готовы мириться, а с какими нет

Sign up to leave a comment.

Articles