Skip to Content
LearnAdvanced UseState Management

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:

ColorChooserNode.vue
<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:

stores/flow.ts
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:

App.vue
<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.

Last updated on