I'm so confused: why @State var inside a View do not change when you call a method on this view from some outer View?

I'm not sure I understand it correctly. In your example you're using doFoo in Button's action, so you're safely outside of read-state and can change @State. You can use withAnimation while you're at it.

Also, you can use @Binding:

struct Foo: View {
  @Binding var flag: Bool

  func doFoo() {
    withAnimation { // You want animation?
      flag = true
    }
  }

  ...
}

struct ConfuseMe: View {
  @State var flag = false

  var body: some View {
    ...
    Foo(flag: $flag)
    ...
  }
}