if I move onChange to Menu, the problem disappeared
Menu("menu") {
Picker("value \(value)", selection: $value) {
Text("A").tag("a")
Text("B").tag("b")
Text("C").tag("c")
}
.pickerStyle(.inline)
}
.onChange(of: value) { oldValue, newValue in
print("onChange", newValue)
}
but my goal is to encapsulate Picker into a controlled component similar to React, so I have to put state inside menu
import SwiftUI
struct TBSelect: View {
let title: String;
let value: String;
let options: Array<TBSelectOption>;
let tip: String;
let onChange: (_ value: String) -> Void;
@State private var innerValue: String;
struct TBSelectOption {
let title: String;
let value: String;
let systemImage: String?;
}
init(title: String, value: String, options: Array<TBSelectOption>, tip: String = "", onChange: @escaping (_ value: String) -> Void) {
_innerValue = State(initialValue: value);
self.title = title
self.value = value
self.options = options
self.tip = tip
self.onChange = onChange;
}
var body: some View {
Picker(title, selection: $innerValue) {
ForEach(options, id: \.value) { option in
if let systemImage = option.systemImage {
Label(option.title, systemImage: systemImage)
.tag(option.value)
} else {
Text(option.title)
.tag(option.value)
}
}
}
.help(tip)
.onChange(of: innerValue) { oldValue, newValue in
onChange(newValue)
}
}
}