InquirerMinimum wage in Central Visayas to rise by P42 per dayThe Jerusalem PostCzech Republic's 6,500-year-old sanctuary found to predate Stonehenge by 1,000 yearsESPN DeportesMourinho y las reglas 'no negociables' en el Real Madrid: "No me traiciones"ESPN'Debate settled': Texas' UT jab at Tennessee leads top trolls of CFB Week 4RTP DesportoEspanha opera reviravolta e bate InglaterraColliderThe 8 Darkest 'Black Mirror' Episodes, RankedSouth China Morning PostHow China is seeking to transform the meaning of great powerBBC NewsAppeal underway after judge blocks Drumcree paradeANSA SportNations League: Repubblica Ceca-Croazia 1-2ZDF heuteAktuelles zum Krieg in der UkraineRadio-Canada« Nous faisons face à une rupture, pas à une transition », reconnaît Anita Anand à l’ONUVanguard10m cash transfer beneficiaries have no phones, social media, says APC chairman
The Daily Newsstand · Free, Always
Saturday, September 26, 2026

Vue: Shared Composable vs Pinia

Translate

Обсудим:  composable, sharedComposable, pinia. Боли, кторые я испытал, когда использовал Pinia. Какие существуют подводные камни в управлении состоянием. Методы и идеи их преодоления. Альтернативы, готовые библиотеки.

Контекст статьи - PWA, в других контекстах тоже будет работать, но это не точно.

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

Кратко по определениям

Composable - фабричная-функция, которая создает объект для хранения состояния. 

Каждый вызов создает новый объект.  Оф. документация рекомендует использовать Composable, как замену миксинам. Это работает так:

  1. компонент вызывает composable функцию

  2. она создает всегда новый  объект, который хранит реактивное состояние в контексте компонента  

  3. компонент использует объект, его свойства, методы, меняет состояние

  4. при уничтожении компонента, контекст уничтожается  вместе объектом и состоянием

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

Shared Composable отличается от composable:

  1. создает новый объект, но в отдельном реактивном контексте. Новый контекст не связан с вызывающим компонентом. Это позволяет хранить объект после  удаления компонента.

  2. имеет счетчик вызовов. При вызове в компоненте счетчик увеличивается, при уничтожении компонента - уменьшается. Новый объект создается только, если счетчик нулевой, уничтожается - если стал нулевым. В остальных случаях возвращается существующий.

Основное назначение - создание, использование  общего состояния, пока оно необходимо хотя бы одной компоненте.

PInia - глобальный менеджер состояний. 

  1. Создает объект состояние во время первого к нему обращение и больше никогда не удаляет. Объект состояние создается в отдельном от компонента реактивном контексте

  2. Автоматически восстанавливает состояние при использовании  SSR

Зачем, если есть Pinia?

Наверно…, если с Pinia нет проблем,  то и не нужно. Но чем больше проект, сложнее связи состояний, бизнес логика и ux, тем больше подводных камней может показать pinia. Особенно, если хочется переиспользовать бизнес логику в другом проекте.

Вот мои боли:

  1. store нужно очищать и удалять, если он не используется. Если этого не сделать, возможны неожиданные эффекты. Об этом нужно помнить. И даже здесь есть особенности:

    1. $dispose не удаляет состояния. При повторном использовании store, его состояние будет восстановлено до предыдущего. Чтобы этого избежать, нужно удалить состояние вручную: delete pinia.state.value[store.$id]

    2. Очистка состоянии дополнительный однотипный код внутри компонент.

    3. store может быть композицией нескольких store или зависеть от них. Pinia ничего не  знает о композиции и зависимостях, поэтому стандартные методы очистки reset и dispose здесь не подходят. Придется самостоятельно придумывать, как очищать. А теперь представьте: один из store, который часть композиции, используются в нескольких местах. Ну и как понять - что нужно очищать, а что нет?

    4. Изменение иерархии компонент может потребовать переноса очистки store в другое место, за этим нужно следить.

  2. фабричные функции store в том виде, в котором они описаны в доке:

    1. сильно усложняют навигацию в IDE. Никогда не попадешь на определение метода, только в return или интерфейс. Особенно боль, когда их много и они большие. 

    2. выглядят как код начала 2000-x. Так  писали, когда не было классов и TypeScript. В то время возможности языка для создания объектов и инкапсулирования были сильно ограничены. Самое печальное, на мой взгляд, что начинающие разработчики читают это и думают - это нормально, так и надо. По-моему - это деградация.

  3. defineStore не явно меняет интерфейс объекта, созданного фабричной функцией.

    1. Об этом нужно помнить, особенно, если использовать деструктуризацию свойств. 

    2. Если возникла необходимость composable сделать общим через defineStore, придется исправлять весь код, который его использовал, потому что интерфейс изменится. 

  4. сложные конструкции из типов в TypeScript.

  5. особенности при SSR. pinia.state.value хранит только то, что вернул публичный интерфейс объекта. Если после гидрации нужно манипулировать состоянием, то можно получить неожиданное поведение, потому что внутреннего состояния не существует. Здесь приходится придумывать разные костыли. Пример:

    1. store категорий имеет публичные интерфейсы для получения категорий в виде плоского списка, дерева и категорий по текущему URL. Все интерфейсы возвращают данные построенные на основе одной  внутренней структуры. Pinia все сериализовала, не спрашивая нас. После восстановления состояния на клиенте PWA будет как минимум 2 проблемы:

      1. все объекты в этих структурах будут разные, даже если у них одинаковый id, потому что они были сериализованы. Будь к этому готов, если ты сравниваешь в коде объекты.  

      2. попытка манипулирования состоянием может вызвать непонятные ошибки, потому что истинное состояние пустое и не было сериализовано

  6. Pinia - это отдельная библиотека, которая оборачивает реактивность Vue  в какое-то отдельное АПИ, что бы …. что? зачем? честно говоря, я не нашел внятного ответа на этот вопрос. Давайте в комментах поищем вместе.

  7. Тестирование store - это отдельная история с композицией и плагинами.

Мой вывод - Pinia пытается решить много проблем и не решает ни одну до конца.

Почему Shared Composable (SC)?

Потому что закрывает 4 из 6 болей описанных выше:

  1. store не нужно очищать и удалять

    1. SC никак не связан с хранением  состояния. SC  больше похож на  контейнер зависимостей, типа https://github.com/microsoft/tsyringe. Токеном доступа к зависимости является функция-провайдер. Хранимый объект может содержать реактивное состояние, но это не обязательно.

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

    3. нет дополнительного кода очистки. Меньше кода - меньше проблем, меньше ошибок.

    4. вместо composable можно всегда смело использовать SC. Объект будет удален, если не используется.

  2. Результат фабричной функции хранится как есть, без изменения интерфейса.

    1. Ничто не мешает использовать внутри фабричной функции new SomeClass. При таком подходе навигация по коду будет простой, вы будете попадать точно на определение метода или свойства в классе, а не куда-то в return.

    2. Тип останется без изменений, нет сложных вычисляемых типов.

    3. Если у вас есть composable,  его легко можно сделать общим не трогая код, который его использовал.

  3. Всё АПИ - это функция, которая регистрирует фабричную функцию в контейнере и создает функцию-провайдер. Но эта функция делает очень важную вещь  -  позволяет очень легко отделить логику и состояние от представления. 

Какие есть альтернативы?

Код создания SC не сложен, вы можете сами написать такую функцию, и все заработает. Пример можно посмотреть здесь. 

Еще есть vue-modeler, там есть DI, расширенные возможности контроля действий, интеграция с SSR. Она закрывает все боли, которые есть у PInia. Отдельная статься на хабре здесь.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.