Because re-evaluating the body of a ForceDirectedGraph can be computationally expensive (especially with large graphs or heavy rich text labels), you should avoid referencing individual observed properties directly within the main graph view's body.
Instead, pass the entire Observable object (ForceDirectedGraphState) to subviews. By referencing the object itself rather than its specific properties (like graphStates.isRunning), the parent view's body will not re-evaluate when those properties change. Use @Bindable in subviews to allow them to mutate the state.
import Grape
struct MyStatefulGraph: View {
@State var graphStates = ForceDirectedGraphState()
var body: some View {
HStack {
// Pass the entire object to avoid body re-evaluation on property changes
ForceDirectedGraph(states: graphStates) {
// ...
} force: {
// ...
}
// Use a separate view to handle interactions
GraphStateToggle(graphStates: graphStates)
}
}
}
struct GraphStateToggle: View {
@Bindable var graphStates: ForceDirectedGraphState
var body: some View {
Button {
graphStates.isRunning.toggle()
} label: {
Text("Toggle Running")
}
}
}