State Management
This guide assumes you’re familiar with custom nodes and the core concepts.
As your app grows, you often need to update the graph from inside a node — a color picker that recolors its own node, say. In React Flow you’d reach for a state library like Zustand to do this. In Vue Flow you usually don’t have to.
You already have a store: useVueFlow()
useVueFlow() returns the same flow instance from anywhere inside <VueFlow> (or a
<VueFlowProvider>), so a custom node can read and update the graph directly, with no external
library and no callbacks threaded through data. To recolor a node from within it, call
updateNodeData:
<script setup lang="ts">
import type { NodeProps } from '@xyflow/vue';
import { useVueFlow } from '@xyflow/vue';
const props = defineProps<NodeProps>();
const { updateNodeData } = useVueFlow();
function onChange(event: Event) {
updateNodeData(props.id, { color: (event.target as HTMLInputElement).value });
}
</script>
<template>
<input class="nodrag" type="color" :value="data.color" @input="onChange">
</template>The nodrag class stops the node from being dragged while the user interacts with the input.
When you want an external store: Pinia
Reach for Pinia when the graph is part of larger app state, or when
components outside the flow need to read or change it. Keep the nodes and edges in the store
and expose actions to mutate them:
import type { Edge, Node } from '@xyflow/vue';
import { defineStore } from 'pinia';
import { shallowRef } from 'vue';
export const useFlowStore = defineStore('flow', () => {
const nodes = shallowRef<Node[]>([/* ... */]);
const edges = shallowRef<Edge[]>([/* ... */]);
function updateNodeColor(id: string, color: string) {
// replace the array so Vue Flow sees the change
nodes.value = nodes.value.map(n =>
n.id === id ? { ...n, data: { ...n.data, color } } : n,
);
}
return { nodes, edges, updateNodeColor };
});Bind the store’s arrays to <VueFlow> with v-model and Vue Flow keeps them in sync as the user
drags, selects, and connects:
<script setup lang="ts">
import { VueFlow } from '@xyflow/vue';
import { storeToRefs } from 'pinia';
import { useFlowStore } from './stores/flow';
const store = useFlowStore();
const { nodes, edges } = storeToRefs(store);
</script>
<template>
<VueFlow v-model:nodes="nodes" v-model:edges="edges" fit-view />
</template>Any component can now call useFlowStore().updateNodeColor(id, color) and the flow updates. If
you’d rather inspect or intercept every change before it’s applied, drop v-model and use the
controlled flow pattern with
@nodes-change / @edges-change instead.