Plugins

The plugin provides a scope to the whole application: the composables read stores from it and call events in it. Required for SSR.

since

EffectorScopePlugin introduced in effector-vue 23.0.0

Plugins

EffectorScopePlugin({ scope, scopeName, forceScope, live })

Formulae

EffectorScopePlugin(options: EffectorScopePluginOptions): Plugin;
app.use(EffectorScopePlugin, options: EffectorScopePluginOptions): App;

Arguments

  1. scope Scope, created by fork
  2. scopeName? custom scopeName (default: root), the legacy string injection key
  3. forceScope? throw instead of falling back to global mode when a composable of this app resolves no scope (default: false)
  4. live? whether the composables subscribe to the scope: false makes them read the scope on access without subscribing to it, as in a server render, true makes them always subscribe (default: false inside renderToString, true elsewhere)
since

forceScope option introduced in effector-vue 23.3.0

since

live option introduced in effector-vue 23.3.0

The plugin provides the scope under the EffectorScopeKey injection key and, for backward compatibility, under the string scopeName.

since

EffectorScopeKey introduced in effector-vue 23.3.0. The plugin throws without a valid scope since effector-vue 23.3.0

Imports

On Vue 3 import the plugin from effector-vue/composition, next to the other composition API methods:

import { EffectorScopePlugin, EffectorScopeKey } from "effector-vue/composition";

Exported from effector-vue/composition since effector-vue 23.2.0. The root entry effector-vue also exports the plugin and keeps doing so for backward compatibility. It is the entry of the Vue 2 API (VueEffector, createComponent), so a Vue 3 app that imports from it pulls in code it never runs.

Examples

Basic Usage

import { createSSRApp } from "vue";
import { EffectorScopePlugin } from "effector-vue/composition";
import { fork } from "effector";
const app = createSSRApp(AppComponent);
const scope = fork();
app.use(
EffectorScopePlugin({
scope,
scopeName: "app-scope-name",
}),
);

Passing options to app.use

since

The app.use(EffectorScopePlugin, options) form works since effector-vue 23.3.0

Both forms install the plugin:

app.use(EffectorScopePlugin({ scope }));
app.use(EffectorScopePlugin, { scope });

Requiring a scope

With forceScope a composable that resolves no scope throws instead of reading global stores:

app.use(EffectorScopePlugin({ scope, forceScope: true }));

The option is read through the injection context, so it covers the calls that see the app: setup, app.runWithContext and anything called before the first await of an async setup. A call that lost the context sees neither the scope nor the option: pass { forceScope: true } to it directly.

How the scope is resolved

since

Resolution through EffectorScopeKey and the scope options of the composables introduced in effector-vue 23.3.0. Before that the scope was read from the string scopeName key of the component instance only

Where the scope options go differs between the composables:

ComposableScope options
useUnit(unit, opts){ scope, forceScope } as the last argument
useStore($store, opts){ scope, forceScope } as the last argument
useGate(Gate, props, opts){ scope, forceScope } as the last argument
useStoreMap(config)scope and forceScope in the config; the positional second argument also works
useProvidedScope(opts){ forceScope } only
useVModel($store, opts){ scope, forceScope } as the last argument; a Vue EffectScope there also works

Whatever the form, the scope is resolved in this order:

  1. the scope option of the call;
  2. the value provided under EffectorScopeKey, if the current call has an injection context;
  3. the legacy string key, when a component instance is available;
  4. global mode, unless forceScope is on.

The legacy string key is read only when nothing is provided under EffectorScopeKey. With the plugin installed, a subtree overrides the scope with provide(EffectorScopeKey, scope); a value provided under the scopeName string no longer does.

The key is created with Symbol.for, so a scope provided by another copy of the package is still found. Providing it by hand is enough, no plugin required:

import { provide } from "vue";
import { EffectorScopeKey } from "effector-vue/composition";
provide(EffectorScopeKey, scope);

Related APIs

Contributors