# Migrating to v4

In v3 there was no Vue package - the docs handed you a directive and composable to copy into your own project. v4 replaces those with the official [`@foresightjs/vue`](/docs/vue/installation.md) package. Install it, delete your copied files, and update a couple of names.

Install the package and delete your hand-rolled `vForesight.ts` / `useForesight.ts`:

```
npm install @foresightjs/vue
```

## Directive[​](#directive "Direct link to Directive")

```
- import { vForesight } from "@/directives/vForesight"
+ import { vForesight } from "@foresightjs/vue"

  app.directive("foresight", vForesight)
```

The usage in your templates is unchanged.

## Composable[​](#composable "Direct link to Composable")

The composable lost the `templateRefKey` string. Instead it returns an `elementRef` function you bind directly:

```
- import { useForesight } from "./composables/useForesight"
+ import { useForesight } from "@foresightjs/vue"

- const { templateRef } = useForesight({ templateRefKey: "myButton", callback })
+ const { elementRef } = useForesight({ callback })
```

```
- <button ref="myButton">Hover</button>
+ <button :ref="elementRef">Hover</button>
```

You also get the [reactive state](/docs/vue/useForesight.md#reactive-state) back as refs instead of a `registerResults` object.

## Core changes[​](#core-changes "Direct link to Core changes")

The core `js.foresight` library also has a few breaking changes. The package handles most of these for you, but they matter if you call `register()` or listen to events directly.

The `register()` call itself is unchanged, but element data is now an immutable state snapshot you can subscribe to - the foundation the wrapper packages are built on:

* **`ForesightElementData` is now `ForesightElementState`.** Your callback receives the flat state snapshot: `callback: (state: ForesightElementState) => void`. See [TypeScript](/docs/getting-started/typescript.md).
* **`register()` returns the state plus `unregister`, `subscribe` and `getSnapshot`.** `isTouchDevice` is gone from the result; touch devices are handled internally by the configured `touchDeviceStrategy` global setting.
* **The `elementDataUpdated`, `elementOptionsUpdated` and `elementReactivated` events are removed.** Per-element changes are now observed through the `subscribe`/`getSnapshot` pair returned by `register()`. The remaining events carry the state in a `state` field instead of `elementData`.
* **Detached elements are parked, not unregistered.** Removing an element from the DOM no longer emits `elementUnregistered` with reason `disconnected`; the element stays registered but inactive and resumes when it reconnects.
* **New `enabled` element option.** Set it to `false` to keep an element registered but excluded from prediction.
